<?php

namespace App\Http\Controllers;

use App\Models\MexcoInvoice;
use App\Models\MexcoPayment;
use App\Services\CampusService;
use App\Services\CheckoutService;
use App\Services\CustomerAuthService;
use App\Services\DemoService;
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 MexcoPortalController extends Controller
{
    public function __construct(
        private CustomerAuthService $auth,
        private OrganisationService $organisations,
        private MeetupService $meetup,
        private UsageService $usage,
        private CheckoutService $checkout,
        private DemoService $demo,
        private CampusService $campus,
    ) {}

    public function dashboard(Request $request): View
    {
        $user = $request->attributes->get('mexcoPortalUser');
        $organisation = $user->organisation;
        $stats = $organisation
            ? $this->organisations->stats($organisation)
            : ['total_events' => 0, 'active_events' => 0, 'completed_events' => 0, 'total_participants' => 0, 'events' => collect()];

        $events = ($stats['events'] ?? collect())->loadMissing(['license.plan', 'license.eventAddons.addon', 'usage']);
        $rows = $events->map(function ($event) {
            return $this->mapEventRow($event);
        });

        $upcoming = $rows->whereIn('status', ['upcoming', 'open'])->count();
        $ongoing = $rows->where('status', 'live')->count();
        $completed = $rows->where('status', 'ended')->count();

        $openOrders = $organisation
            ? $this->checkout->openOrdersForOrganisation($organisation->id)
            : collect();

        $recentPayments = $organisation
            ? MexcoPayment::query()
                ->whereHas('invoice', fn ($q) => $q->where('organisation_id', $organisation->id))
                ->with('invoice.event')
                ->orderByDesc('paid_at')
                ->limit(5)
                ->get()
            : collect();

        $pendingInvoices = $organisation
            ? MexcoInvoice::query()
                ->where('organisation_id', $organisation->id)
                ->whereIn('status', [MexcoInvoice::STATUS_PENDING, MexcoInvoice::STATUS_DRAFT])
                ->with('event')
                ->orderByDesc('updated_at')
                ->limit(5)
                ->get()
            : collect();

        $firstWithPlan = $rows->first(fn ($row) => (bool) ($row['event']->license?->plan));
        $currentPlan = $firstWithPlan['event']->license?->plan ?? null;
        $upcomingExpiry = $rows
            ->map(fn ($row) => $row['event']->license?->ends_at)
            ->filter()
            ->sort()
            ->first();

        $activeDemo = $organisation
            ? $this->demo->activeDemoForOrganisation((int) $organisation->id)
            : null;

        $campusApplication = $organisation
            ? $this->campus->latestForOrganisation((int) $organisation->id)
            : null;

        return view('portal.dashboard', [
            'user' => $user,
            'organisation' => $organisation,
            'rows' => $rows,
            'openOrders' => $openOrders,
            'recentPayments' => $recentPayments,
            'pendingInvoices' => $pendingInvoices,
            'currentPlan' => $currentPlan,
            'upcomingExpiry' => $upcomingExpiry,
            'canStartDemo' => $this->demo->canStart($user),
            'demoLimits' => $this->demo->isEnabled() ? $this->demo->limitations() : null,
            'activeDemo' => $activeDemo,
            'campusApplication' => $campusApplication,
            'kpis' => [
                'total' => $rows->count(),
                'upcoming' => $upcoming,
                'ongoing' => $ongoing,
                'completed' => $completed,
                'participants' => $stats['total_participants'] ?? 0,
            ],
        ]);
    }

    public function showCampusApply(Request $request): View|RedirectResponse
    {
        $user = $request->attributes->get('mexcoPortalUser');
        $organisation = $user->organisation;
        $pending = $organisation
            ? $this->campus->pendingForOrganisation((int) $organisation->id)
            : null;

        if ($pending) {
            return redirect()->route('mexco.portal.dashboard')
                ->with('success', 'Your Campus Plan application '.$pending->reference_no.' is awaiting Super Admin approval.');
        }

        return view('portal.campus-apply', [
            'user' => $user,
            'organisation' => $organisation,
        ]);
    }

    public function submitCampusApply(Request $request): RedirectResponse
    {
        $user = $request->attributes->get('mexcoPortalUser');

        $data = $request->validate([
            'faculty' => 'required|string|max:255',
            'student_organisation' => 'required|string|max:255',
            'event_name' => 'required|string|max:255',
            'event_date' => 'required|date|after_or_equal:today',
            'expected_participants' => 'required|integer|min:1|max:100000',
            'sessions_count' => 'required|integer|min:0|max:10000',
            'booths_count' => 'required|integer|min:0|max:10000',
            'event_objective' => 'required|string|max:5000',
            'promotional_exposure' => 'required|string|max:5000',
            'sponsorship_letter' => 'required|file|mimes:pdf,doc,docx,jpg,jpeg,png|max:10240',
        ]);

        $letter = $request->file('sponsorship_letter');
        $letterPath = $letter->store('campus/sponsorship-letters', 'local');

        $application = $this->campus->submitForOrganisationUser($user->loadMissing('organisation'), [
            ...$data,
            'institution' => $user->organisation?->name,
            'contact_person' => $user->name,
            'contact_email' => $user->email,
            'applicant_phone' => $user->phone,
            'sponsorship_letter_path' => $letterPath,
            'sponsorship_letter_name' => $letter->getClientOriginalName(),
        ]);

        return redirect()->route('mexco.portal.dashboard')
            ->with('success', 'Campus Plan application '.$application->reference_no.' submitted. Please wait for Super Admin approval.');
    }

    public function startDemo(Request $request): RedirectResponse
    {
        $user = $request->attributes->get('mexcoPortalUser');

        try {
            $demo = $this->demo->start($user);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return redirect()->route('mexco.portal.dashboard')
                ->withErrors($e->errors());
        }

        return redirect()->route('mexco.portal.dashboard')
            ->with('success', 'Demo started. Full features are unlocked with limited capacity for '.$this->demo->durationDays().' days.')
            ->with('demo_organiser_username', $demo['event']->organiser_username)
            ->with('demo_organiser_password', $demo['organiser_password']);
    }

    public function events(Request $request): View
    {
        $user = $request->attributes->get('mexcoPortalUser');
        $organisation = $user->organisation;
        $tab = $request->query('tab', 'all');

        $events = $organisation
            ? $organisation->events()->with(['license.plan', 'license.eventAddons.addon', 'usage'])->orderByDesc('created_at')->get()
            : collect();

        $rows = $events->map(fn ($event) => $this->mapEventRow($event));

        $filtered = match ($tab) {
            'upcoming' => $rows->whereIn('status', ['upcoming', 'open']),
            'ongoing' => $rows->where('status', 'live'),
            'completed' => $rows->where('status', 'ended'),
            default => $rows,
        };

        return view('portal.events', [
            'user' => $user,
            'organisation' => $organisation,
            'rows' => $filtered->values(),
            'tab' => $tab,
            'activeDemo' => $organisation
                ? $this->demo->activeDemoForOrganisation((int) $organisation->id)
                : null,
            'counts' => [
                'all' => $rows->count(),
                'upcoming' => $rows->whereIn('status', ['upcoming', 'open'])->count(),
                'ongoing' => $rows->where('status', 'live')->count(),
                'completed' => $rows->where('status', 'ended')->count(),
            ],
        ]);
    }

    protected function mapEventRow($event): array
    {
        $status = $this->meetup->eventAvailability($event);
        $usage = $this->usage->summary($event->id);
        $addons = $event->license?->eventAddons
            ?->filter(fn ($a) => in_array($a->status, ['active', 'pending'], true))
            ->map(fn ($a) => $a->addon?->name)
            ->filter()
            ->values()
            ->all() ?? [];

        return [
            'event' => $event,
            'status' => $status,
            'statusLabel' => match ($status) {
                'upcoming' => 'Upcoming',
                'live' => 'Ongoing',
                'ended' => 'Completed',
                default => 'Open',
            },
            'usage' => $usage['participants'] ?? ['current' => 0, 'limit' => null, 'percent' => null],
            'schedule' => $this->meetup->eventDurationLabel($event),
            'addons' => $addons,
            'licenseStatus' => $event->license?->status,
            'expiry' => $event->license?->ends_at,
        ];
    }
}
