<?php

namespace App\Http\Controllers\PublicSite;

use App\Enums\StudyMode;
use App\Http\Controllers\Controller;
use App\Models\Intake;
use App\Models\Programme;
use App\Models\School;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;

class ProgrammeController extends Controller
{
    /** Searchable, filterable catalogue (PRD 9). */
    public function index(Request $request): View
    {
        $filters = $request->validate([
            'q' => ['nullable', 'string', 'max:120'],
            'school' => ['nullable', 'integer', 'exists:schools,id'],
            'level' => ['nullable', 'string', 'max:40'],
            'mode' => ['nullable', 'string', 'max:30'],
            'campus' => ['nullable', 'string', 'max:100'],
        ]);

        $programmes = Programme::active()
            ->with('school:id,name,slug')
            ->search($filters['q'] ?? null)
            ->forSchool($filters['school'] ?? null)
            ->level($filters['level'] ?? null)
            ->studyMode($filters['mode'] ?? null)
            ->campus($filters['campus'] ?? null)
            ->ordered()
            ->paginate(12)
            ->withQueryString();

        return view('public.programmes.index', [
            'programmes' => $programmes,
            'schools' => School::active()->ordered()->get(['id', 'name']),
            'levels' => [
                Programme::LEVEL_UNDERGRADUATE => 'Undergraduate',
                Programme::LEVEL_DIPLOMA => 'Diploma',
                Programme::LEVEL_CERTIFICATE => 'Certificate',
                Programme::LEVEL_POSTGRADUATE => 'Postgraduate',
            ],
            'modes' => collect(StudyMode::cases())->mapWithKeys(fn ($m) => [$m->value => $m->label()])->all(),
            'campuses' => $this->campuses(),
            'filters' => $filters,
        ]);
    }

    public function show(Programme $programme): View
    {
        abort_unless($programme->status->value === 'active', 404);

        $programme->load(['school', 'department', 'requirements']);

        return view('public.programmes.show', [
            'programme' => $programme,
            'intake' => Intake::current(),
            'related' => Programme::active()
                ->where('school_id', $programme->school_id)
                ->whereKeyNot($programme->id)
                ->ordered()
                ->take(3)
                ->get(),
        ]);
    }

    /** Distinct campuses across the catalogue, for the filter list. */
    protected function campuses(): array
    {
        return Programme::active()
            ->pluck('campuses')
            ->flatten()
            ->filter()
            ->unique()
            ->sort()
            ->values()
            ->mapWithKeys(fn (string $c) => [$c => $c])
            ->all();
    }
}
