<?php

namespace App\Http\Controllers;

use App\Models\MexcoCampusApplication;
use App\Models\MexcoOrganisation;
use App\Services\AuditService;
use App\Services\CampusService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\StreamedResponse;

class MexcoSuperAdminCampusController extends Controller
{
    public function __construct(
        private CampusService $campus,
        private AuditService $audit,
    ) {}

    public function index(Request $request): View
    {
        $status = $request->input('status', '');
        $q = strtolower(trim($request->input('q', '')));

        $applications = MexcoCampusApplication::query()
            ->with(['organisation', 'event', 'license'])
            ->when($status === 'pending', fn ($query) => $query->whereIn('status', [
                MexcoCampusApplication::STATUS_SUBMITTED,
                MexcoCampusApplication::STATUS_UNDER_REVIEW,
            ]))
            ->when($status && $status !== 'pending', fn ($query) => $query->where('status', $status))
            ->when($q, fn ($query) => $query->where(function ($sub) use ($q) {
                $sub->where('reference_no', 'like', "%{$q}%")
                    ->orWhere('institution', 'like', "%{$q}%")
                    ->orWhere('event_name', 'like', "%{$q}%")
                    ->orWhere('contact_email', 'like', "%{$q}%");
            }))
            ->orderByDesc('created_at')
            ->get();

        $stats = $this->campus->dashboardStats();

        return view('super-admin.campus.index', compact('applications', 'stats', 'status', 'q'));
    }

    public function create(): View
    {
        return view('super-admin.campus.form', [
            'application' => null,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'institution' => 'required|string|max:255',
            'faculty' => 'nullable|string|max:255',
            'student_organisation' => 'nullable|string|max:255',
            'event_name' => 'required|string|max:255',
            'event_date' => 'nullable|date',
            'expected_participants' => 'nullable|integer|min:1',
            'sessions_count' => 'nullable|integer|min:0',
            'booths_count' => 'nullable|integer|min:0',
            'event_objective' => 'nullable|string',
            'contact_person' => 'required|string|max:255',
            'contact_email' => 'required|email|max:255',
            'requested_sponsorship' => 'nullable|string',
            'promotional_exposure' => 'nullable|string',
            'sponsorship_value_cents' => 'nullable|integer|min:0',
        ]);

        $application = $this->campus->createApplication($data);

        return redirect()->route('mexco.super.campus.show', $application)
            ->with('success', 'Campus application '.$application->reference_no.' recorded.');
    }

    public function show(MexcoCampusApplication $application): View
    {
        $application->load(['organisation', 'event.license.plan', 'license.plan', 'reviewer']);
        $organisations = MexcoOrganisation::query()
            ->whereIn('status', ['active', 'pending'])
            ->orderBy('name')
            ->get();

        return view('super-admin.campus.show', compact('application', 'organisations'));
    }

    public function downloadLetter(MexcoCampusApplication $application): StreamedResponse
    {
        if (! $application->hasSponsorshipLetter() || ! Storage::disk('local')->exists($application->sponsorship_letter_path)) {
            abort(404, 'Sponsorship letter not found.');
        }

        return Storage::disk('local')->download(
            $application->sponsorship_letter_path,
            $application->sponsorship_letter_name ?: 'sponsorship-letter'
        );
    }

    public function review(MexcoCampusApplication $application): RedirectResponse
    {
        $this->campus->markUnderReview($application, session('meetup_super_admin_id'));

        return back()->with('success', 'Application marked as under review.');
    }

    public function approve(Request $request, MexcoCampusApplication $application): RedirectResponse
    {
        $data = $request->validate([
            'organisation_id' => 'nullable|exists:mexco_organisations,id',
            'event_id' => 'nullable|string|max:64|regex:/^[a-z0-9_-]+$/i',
            'venue' => 'nullable|string|max:255',
            'organiser_password' => 'nullable|string|min:4|max:64',
            'sponsorship_value_cents' => 'nullable|integer|min:0',
            'review_notes' => 'nullable|string',
        ]);

        $password = $data['organiser_password'] ?? Str::random(10);

        $application = $this->campus->approve($application, [
            'organisation_id' => $data['organisation_id'] ?? null,
            'event_id' => $data['event_id'] ?? null,
            'venue' => $data['venue'] ?? null,
            'organiser_password' => $password,
            'sponsorship_value_cents' => $data['sponsorship_value_cents'] ?? null,
            'review_notes' => $data['review_notes'] ?? null,
        ], session('meetup_super_admin_id'));

        $this->audit->log('campus.approved', MexcoCampusApplication::class, (string) $application->id, null, [
            'reference_no' => $application->reference_no,
            'event_id' => $application->event_id,
        ]);

        return redirect()->route('mexco.super.campus.show', $application)
            ->with('success', 'Campus sponsorship approved. Event '.$application->event_id.' created. The applicant can now sign in to My MeXCo.')
            ->with('organiser_password', $password);
    }

    public function reject(Request $request, MexcoCampusApplication $application): RedirectResponse
    {
        $data = $request->validate([
            'review_notes' => 'required|string|max:2000',
        ]);

        $this->campus->reject($application, $data['review_notes'], session('meetup_super_admin_id'));

        $this->audit->log('campus.rejected', MexcoCampusApplication::class, (string) $application->id, null, [
            'reference_no' => $application->reference_no,
        ]);

        return redirect()->route('mexco.super.campus.show', $application)
            ->with('success', 'Application rejected.');
    }

    public function extendRetention(Request $request, MexcoCampusApplication $application): RedirectResponse
    {
        $data = $request->validate([
            'extra_days' => 'required|integer|min:1|max:90',
        ]);

        if (! $application->license) {
            return back()->with('error', 'No license linked to this application.');
        }

        $this->campus->extendRetention($application->license, $data['extra_days']);

        return back()->with('success', 'Retention extended by '.$data['extra_days'].' days.');
    }
}
