<?php

namespace App\Http\Controllers\Admin\School;

use App\Http\Controllers\Admin\PageController;
use App\Models\AcademicYear;
use App\Models\Club;
use App\Models\Staff;
use App\Models\Student;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class ClubController extends PageController
{
    /** @var list<string> */
    private const CATEGORIES = ['sports', 'arts', 'academic', 'service', 'religious', 'technology', 'other'];

    public function index(): View
    {
        $clubs = Club::query()
            ->with(['patron', 'academicYear'])
            ->withCount('students')
            ->orderBy('name')
            ->paginate(25);

        return $this->page('admin.clubs.index', [
            'crumbTitle' => 'Clubs',
            'crumbSub' => 'Extracurricular groups',
            'clubs' => $clubs,
        ]);
    }

    public function create(): View
    {
        return $this->page('admin.clubs.create', [
            'crumbTitle' => 'Clubs',
            'crumbSub' => 'New club',
            'categories' => self::CATEGORIES,
            'academicYears' => AcademicYear::query()->orderByDesc('starts_on')->get(),
            'staffMembers' => Staff::query()->where('status', 'active')->orderBy('last_name')->get(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $this->validateClub($request);
        $data['discussion_enabled'] = $request->boolean('discussion_enabled');

        $club = Club::query()->create($data);

        return redirect()
            ->route('school.clubs.show', $club)
            ->with('success', 'Club created successfully.');
    }

    public function show(Club $club): View
    {
        $club->load(['patron', 'academicYear', 'students']);

        $availableStudents = Student::query()
            ->where('status', 'active')
            ->whereDoesntHave('clubs', fn ($q) => $q->where('clubs.id', $club->id))
            ->orderBy('last_name')
            ->limit(100)
            ->get();

        return $this->page('admin.clubs.show', [
            'crumbTitle' => 'Clubs',
            'crumbSub' => $club->name,
            'club' => $club,
            'availableStudents' => $availableStudents,
        ]);
    }

    public function edit(Club $club): View
    {
        return $this->page('admin.clubs.edit', [
            'crumbTitle' => 'Clubs',
            'crumbSub' => 'Edit '.$club->name,
            'club' => $club,
            'categories' => self::CATEGORIES,
            'academicYears' => AcademicYear::query()->orderByDesc('starts_on')->get(),
            'staffMembers' => Staff::query()->where('status', 'active')->orderBy('last_name')->get(),
        ]);
    }

    public function update(Request $request, Club $club): RedirectResponse
    {
        $data = $this->validateClub($request, $club);
        $data['discussion_enabled'] = $request->boolean('discussion_enabled');

        $club->update($data);

        return redirect()
            ->route('school.clubs.show', $club)
            ->with('success', 'Club updated successfully.');
    }

    public function destroy(Club $club): RedirectResponse
    {
        $club->delete();

        return $this->redirectWithSuccess('school.clubs.index', 'Club removed.');
    }

    public function assign(Request $request, Club $club): RedirectResponse
    {
        $validated = $request->validate([
            'student_ids' => ['required', 'array', 'min:1'],
            'student_ids.*' => ['exists:students,id'],
            'role' => ['nullable', 'string', 'max:30'],
        ]);

        if ($club->max_members && ($club->activeMembersCount() + count($validated['student_ids'])) > $club->max_members) {
            return back()->withErrors(['student_ids' => 'Club member limit would be exceeded.']);
        }

        foreach ($validated['student_ids'] as $studentId) {
            $club->students()->syncWithoutDetaching([
                $studentId => [
                    'role' => $validated['role'] ?? 'member',
                    'joined_on' => now()->toDateString(),
                    'status' => 'active',
                ],
            ]);
        }

        return back()->with('success', count($validated['student_ids']).' student(s) assigned to '.$club->name.'.');
    }

    public function removeStudent(Club $club, Student $student): RedirectResponse
    {
        $club->students()->detach($student->id);

        return back()->with('success', 'Student removed from club.');
    }

    /**
     * @return array<string, mixed>
     */
    private function validateClub(Request $request, ?Club $club = null): array
    {
        return $request->validate([
            'name' => ['required', 'string', 'max:100'],
            'code' => ['required', 'string', 'max:30', 'unique:clubs,code,'.$club?->id],
            'description' => ['nullable', 'string'],
            'category' => ['nullable', 'string', 'max:50'],
            'patron_id' => ['nullable', 'exists:staff,id'],
            'academic_year_id' => ['nullable', 'exists:academic_years,id'],
            'max_members' => ['nullable', 'integer', 'min:1', 'max:500'],
            'status' => ['nullable', 'string', 'max:30'],
            'discussion_enabled' => ['sometimes', 'boolean'],
        ]);
    }
}
