<?php

namespace App\Http\Controllers\Teacher;

use App\Http\Controllers\Admin\PageController;
use App\Http\Controllers\Concerns\AuthorizesClubAccess;
use App\Models\Club;
use App\Services\School\ClubDiscussionService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ClubController extends PageController
{
    use AuthorizesClubAccess;

    public function __construct(private readonly ClubDiscussionService $discussions) {}

    public function index(): View
    {
        $staffId = auth()->user()?->staff_id;

        $clubs = Club::query()
            ->when($staffId, fn ($q) => $q->where('patron_id', $staffId))
            ->with(['patron'])
            ->withCount('students')
            ->orderBy('name')
            ->get();

        return $this->page('teacher.clubs.index', [
            'crumbTitle' => 'Clubs',
            'crumbSub' => 'Patron clubs & discussions',
            'clubs' => $clubs,
        ]);
    }

    public function show(Club $club): View
    {
        $this->authorizeClub($club);

        $messages = $this->discussions->fetchMessages($club);

        return $this->page('teacher.clubs.show', [
            'crumbTitle' => $club->name,
            'crumbSub' => 'Club discussion',
            'club' => $club->load(['patron', 'students']),
            'messages' => $messages,
            'allowedEmojis' => ClubDiscussionService::ALLOWED_EMOJIS,
            'discussionRoutePrefix' => 'teacher.clubs',
        ]);
    }

    public function storeMessage(Request $request, Club $club): RedirectResponse|JsonResponse
    {
        $this->authorizeClub($club);

        $validated = $request->validate([
            'body' => ['nullable', 'string', 'max:5000'],
            'attachment' => ['nullable', 'file', 'max:10240', 'mimes:jpg,jpeg,png,gif,webp,pdf,doc,docx,xls,xlsx,ppt,pptx,txt,mp3,wav,mp4'],
        ]);

        $message = $this->discussions->postMessage(
            $club,
            auth()->user(),
            $validated,
            $request->file('attachment'),
        );

        if ($request->wantsJson()) {
            return response()->json(['message' => $this->formatMessage($message)]);
        }

        return back()->with('success', 'Message sent.');
    }

    public function messages(Club $club, Request $request): JsonResponse
    {
        $this->authorizeClub($club);

        $afterId = $request->integer('after_id') ?: null;
        $messages = $this->discussions->fetchMessages($club, $afterId);

        return response()->json([
            'messages' => $messages->map(fn ($m) => $this->formatMessage($m)),
        ]);
    }

    public function react(Request $request, Club $club, int $messageId): JsonResponse
    {
        $this->authorizeClub($club);

        $validated = $request->validate([
            'emoji' => ['required', 'string', 'max:16'],
        ]);

        $message = $club->messages()->findOrFail($messageId);
        $reaction = $this->discussions->toggleReaction($message, auth()->user(), $validated['emoji']);

        return response()->json([
            'reactions' => $message->fresh('reactions.user')->reactions->map(fn ($r) => [
                'emoji' => $r->emoji,
                'user' => $r->user?->name,
            ]),
        ]);
    }

    /**
     * @return array<string, mixed>
     */
    private function formatMessage(\App\Models\ClubMessage $message): array
    {
        return [
            'id' => $message->id,
            'body' => $message->body,
            'message_type' => $message->message_type,
            'user' => $message->user?->name,
            'user_id' => $message->user_id,
            'is_mine' => $message->user_id === auth()->id(),
            'created_at' => $message->created_at?->format('d M Y H:i'),
            'attachments' => $message->attachments->map(fn ($a) => [
                'url' => $a->url(),
                'name' => $a->file_name,
                'type' => $a->attachment_type,
            ]),
            'reactions' => $message->reactions->groupBy('emoji')->map(fn ($group, $emoji) => [
                'emoji' => $emoji,
                'count' => $group->count(),
            ])->values(),
        ];
    }
}
