<?php

namespace App\Http\Controllers;

use App\Models\MexcoInvoice;
use App\Models\MexcoOrganisation;
use App\Models\MeetupEvent;
use App\Models\MeetupSuperAdmin;
use App\Services\AnalyticsService;
use App\Services\AuditService;
use App\Services\BillingService;
use App\Services\CampusService;
use App\Services\EntitlementService;
use App\Services\MeetupService;
use App\Services\OrganisationService;
use App\Services\UsageService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class MeetupSuperAdminController extends Controller
{
    public function __construct(
        private MeetupService $meetup,
        private EntitlementService $entitlements,
        private UsageService $usage,
        private OrganisationService $organisations,
        private CampusService $campus,
        private BillingService $billing,
        private AuditService $audit,
        private AnalyticsService $analytics,
    ) {}

    public function showLogin(): View
    {
        return view('super-admin.login');
    }

    public function login(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'email' => 'required|email',
            'password' => 'required|string',
        ]);

        $admin = MeetupSuperAdmin::query()->where('email', $data['email'])->first();

        if (! $admin || ! $admin->verifyPassword($data['password'])) {
            return back()->withInput()->with('error', 'Invalid email or password.');
        }

        if (! $admin->isActive()) {
            return back()->withInput()->with('error', 'This admin account is suspended.');
        }

        $admin->update(['last_login_at' => now()]);

        $request->session()->put('meetup_super_authenticated', true);
        $request->session()->put('meetup_super_admin_id', $admin->id);
        $request->session()->put('meetup_super_admin_name', $admin->name);

        return redirect()->route('mexco.super.dashboard');
    }

    public function logout(Request $request): RedirectResponse
    {
        $request->session()->forget([
            'meetup_super_authenticated',
            'meetup_super_admin_id',
            'meetup_super_admin_name',
        ]);

        return redirect()->route('mexco.super.login')->with('success', 'Signed out.');
    }

    public function dashboard(): View
    {
        $events = MeetupEvent::query()
            ->with(['license.plan', 'organisation'])
            ->orderByDesc('created_at')
            ->get();

        $summaries = [];
        foreach ($events as $event) {
            $summaries[$event->id] = $this->meetup->eventSummary($event);
        }

        $campusStats = $this->campus->dashboardStats();
        $billingStats = $this->billing->dashboardStats();
        $analyticsOverview = $this->analytics->platformOverview();
        $eventsByPlan = $this->analytics->eventsByPlan();

        return view('super-admin.dashboard', compact(
            'events',
            'summaries',
            'campusStats',
            'billingStats',
            'analyticsOverview',
            'eventsByPlan',
        ));
    }

    public function events(): View
    {
        $events = MeetupEvent::query()
            ->with(['license.plan', 'organisation', 'usage'])
            ->orderByDesc('created_at')
            ->get();

        $summaries = [];
        $usageSummaries = [];
        foreach ($events as $event) {
            $summaries[$event->id] = $this->meetup->eventSummary($event);
            $usageSummaries[$event->id] = $this->usage->summary($event->id);
        }

        $invoices = MexcoInvoice::query()
            ->whereIn('event_id', $events->pluck('id'))
            ->get()
            ->keyBy('event_id');

        return view('super-admin.events.index', compact(
            'events',
            'summaries',
            'usageSummaries',
            'invoices',
        ));
    }

    public function createEvent(): View
    {
        return view('super-admin.events.form', [
            'event' => null,
            'plans' => $this->entitlements->planOptions(),
            'organisations' => MexcoOrganisation::query()->where('status', 'active')->orderBy('name')->get(),
            'entitlementMap' => [],
            'limits' => [],
        ]);
    }

    public function storeEvent(Request $request): RedirectResponse
    {
        $data = $request->validate([
            'name' => 'required|string|max:255',
            'venue' => 'nullable|string|max:255',
            'dates' => 'nullable|string|max:255',
            'event_id' => 'nullable|string|max:64|regex:/^[a-z0-9]+$/|unique:meetup_events,id',
            'plan_code' => 'required|string|exists:mexco_plans,code',
            'organisation_id' => 'required|exists:mexco_organisations,id',
            'organiser_username' => 'required|email|max:255|unique:meetup_events,organiser_username',
            'organiser_password' => 'required|string|min:6|confirmed',
            'is_virtual' => 'nullable|boolean',
            'allow_voting' => 'nullable|boolean',
            'allow_floor_plan' => 'nullable|boolean',
            'starts_at' => 'nullable|date',
            'ends_at' => 'nullable|date|after_or_equal:starts_at',
        ]);

        $event = $this->meetup->createEvent([
            'id' => $data['event_id'] ?? null,
            'organisation_id' => $data['organisation_id'],
            'name' => $data['name'],
            'venue' => $data['venue'] ?? '',
            'dates' => $data['dates'] ?? '',
            'organiser_username' => $data['organiser_username'],
            'organiser_password' => $data['organiser_password'],
            'is_virtual' => $request->boolean('is_virtual'),
            'allow_voting' => $request->boolean('allow_voting'),
            'allow_floor_plan' => $request->boolean('allow_floor_plan'),
            'starts_at' => $data['starts_at'] ?? null,
            'ends_at' => $data['ends_at'] ?? null,
        ]);

        $license = $this->entitlements->assignPlan($event->id, $data['plan_code']);
        $this->usage->recalculate($event->id);
        $this->entitlements->syncLegacyFlags($event->fresh());
        $this->organisations->migrateLegacyOrganiser($event->fresh());
        $this->billing->createDraftInvoiceForLicense($event->fresh(), $license);

        $this->audit->log('event.created', MeetupEvent::class, $event->id, null, [
            'name' => $event->name,
            'plan_code' => $data['plan_code'],
            'organisation_id' => $data['organisation_id'],
        ]);

        return redirect()->route('mexco.super.events')
            ->with('success', 'Event "'.$event->name.'" created with default roles and booths.');
    }

    public function editEvent(string $eventId): View
    {
        $event = MeetupEvent::query()->with(['license.plan', 'organisation'])->findOrFail($eventId);

        return view('super-admin.events.form', [
            'event' => $event,
            'plans' => $this->entitlements->planOptions(),
            'organisations' => MexcoOrganisation::query()->orderBy('name')->get(),
            'entitlementMap' => $this->entitlements->entitlementsForEvent($eventId),
            'limits' => $this->entitlements->limits($eventId),
        ]);
    }

    public function updateEvent(Request $request, string $eventId): RedirectResponse
    {
        $data = $request->validate([
            'name' => 'required|string|max:255',
            'venue' => 'nullable|string|max:255',
            'dates' => 'nullable|string|max:255',
            'event_name' => 'nullable|string|max:255',
            'plan_code' => 'required|string|exists:mexco_plans,code',
            'organisation_id' => 'required|exists:mexco_organisations,id',
            'organiser_username' => 'required|email|max:255|unique:meetup_events,organiser_username,'.$eventId.',id',
            'organiser_password' => 'nullable|string|min:6|confirmed',
            'is_virtual' => 'nullable|boolean',
            'allow_voting' => 'nullable|boolean',
            'allow_floor_plan' => 'nullable|boolean',
            'starts_at' => 'nullable|date',
            'ends_at' => 'nullable|date|after_or_equal:starts_at',
        ]);

        $this->meetup->updateEventRecord($eventId, [
            'name' => $data['name'],
            'venue' => $data['venue'] ?? '',
            'dates' => $data['dates'] ?? '',
            'event_name' => $data['event_name'] ?? $data['name'],
            'organisation_id' => $data['organisation_id'],
            'organiser_username' => $data['organiser_username'],
            'organiser_password' => $data['organiser_password'] ?? null,
            'is_virtual' => $request->boolean('is_virtual'),
            'allow_voting' => $request->boolean('allow_voting'),
            'allow_floor_plan' => $request->boolean('allow_floor_plan'),
            'starts_at' => $data['starts_at'] ?? null,
            'ends_at' => $data['ends_at'] ?? null,
        ]);

        $this->entitlements->assignPlan($eventId, $data['plan_code']);
        $event = MeetupEvent::query()->findOrFail($eventId);
        $this->entitlements->syncLegacyFlags($event);
        $this->organisations->migrateLegacyOrganiser($event->fresh());

        $this->audit->log('event.updated', MeetupEvent::class, $eventId, null, [
            'name' => $data['name'],
            'plan_code' => $data['plan_code'],
        ]);

        return redirect()->route('mexco.super.events')
            ->with('success', 'Event updated.');
    }

    public function destroyEvent(string $eventId): RedirectResponse
    {
        $event = MeetupEvent::query()->findOrFail($eventId);
        $name = $event->name;
        $this->meetup->deleteEvent($eventId);

        $this->audit->log('event.deleted', MeetupEvent::class, $eventId, ['name' => $name], null);

        return redirect()->route('mexco.super.events')
            ->with('success', 'Event "'.$name.'" deleted.');
    }

    public function enterOrganiser(Request $request, string $eventId): RedirectResponse
    {
        MeetupEvent::query()->findOrFail($eventId);

        $request->session()->put('meetup_admin_event', $eventId);
        $request->session()->put('meetup_admin_authenticated', true);

        return redirect()->route('mexco.admin.dashboard')
            ->with('success', 'Opened organiser panel for this event.');
    }
}
