<?php

namespace App\Controllers;

use App\Models\EventModel;
use App\Models\EventRegistrationFieldModel;
use App\Models\EventRegistrationModel;
use Config\Lookups;

/**
 * Organizer-facing (protected by the 'organizerAuth' filter — see
 * app/Config/Routes.php's organizer/* group). Extends the regular
 * BaseController, not BaseAdminController — organizers ARE tenant-scoped
 * (unlike Super Admin), so the normal tenant-DB-backed logActivity()/
 * TenantModel machinery is correct here.
 *
 * showEvent() introduces the one genuinely new authorization pattern in
 * this app: every other check is role-based (RoleAccess filter) or
 * realm-based (which session you're logged into) — nothing else checks
 * "does this specific record belong to the logged-in party." Kept as a
 * simple inline check rather than a generic abstraction, since this is
 * currently the only call site that needs it.
 */
class EventOrganizerController extends BaseController
{
    public function dashboard()
    {
        $events = (new EventModel())->where('organizer_id', session('organizerId'))->orderBy('event_date', 'desc')->findAll();

        return view('organizer/dashboard', [
            'pageTitle' => 'My Events',
            'events'    => $events,
            'lookups'   => new Lookups(),
        ]);
    }

    public function showEvent(int $id)
    {
        $event = $this->ownedEvent($id);

        if ($event === null) {
            return redirect()->to('organizer/dashboard')->with('error', 'Event not found.');
        }

        $eventModel  = new EventModel();
        $token       = $eventModel->ensurePublicToken($id);
        $registerUrl = site_url('event-register/' . $token);
        $checkinUrl  = site_url('event-checkin/' . $token);
        $qrDataUri   = $eventModel->registrationQrDataUri($checkinUrl);

        $registrations = (new EventRegistrationModel())->forEvent($id);
        $customFields  = (new EventRegistrationFieldModel())->forEvent($id);

        return view('organizer/events/show', [
            'pageTitle'     => $event->event_name,
            'event'         => $event,
            'registerUrl'   => $registerUrl,
            'checkinUrl'    => $checkinUrl,
            'qrDataUri'     => $qrDataUri,
            'registrations' => $registrations,
            'customFields'  => $customFields,
            'lookups'       => new Lookups(),
        ]);
    }

    public function addField(int $id)
    {
        if ($this->ownedEvent($id) === null) {
            return redirect()->to('organizer/dashboard')->with('error', 'Event not found.');
        }

        $fields = new EventRegistrationFieldModel();
        $data = [
            'event_id'    => $id,
            'label'       => $this->request->getPost('label'),
            'field_type'  => $this->request->getPost('field_type'),
            'options'     => $this->encodeOptions($this->request->getPost('options')),
            'is_required' => $this->request->getPost('is_required') ? 1 : 0,
            'sort_order'  => $fields->nextSortOrder($id),
        ];

        if (! $fields->insert($data)) {
            return $this->redirectWithModelErrors($fields);
        }

        $this->logActivity('events', 'Organizer ' . session('organizerName') . ' added registration question "' . $data['label'] . '" to event #' . $id . '.');

        return redirect()->to('organizer/events/' . $id)->with('success', 'Question added.');
    }

    public function deleteField(int $id, int $fieldId)
    {
        if ($this->ownedEvent($id) === null) {
            return redirect()->to('organizer/dashboard')->with('error', 'Event not found.');
        }

        $fields = new EventRegistrationFieldModel();

        if ($fields->where('event_id', $id)->find($fieldId) === null) {
            return redirect()->to('organizer/events/' . $id)->with('error', 'Question not found.');
        }

        $fields->delete($fieldId);
        $this->logActivity('events', 'Organizer ' . session('organizerName') . ' removed a registration question from event #' . $id . '.');

        return redirect()->to('organizer/events/' . $id)->with('success', 'Question removed.');
    }

    public function moveFieldUp(int $id, int $fieldId)
    {
        if ($this->ownedEvent($id) === null) {
            return redirect()->to('organizer/dashboard')->with('error', 'Event not found.');
        }

        (new EventRegistrationFieldModel())->moveUp($fieldId, $id);

        return redirect()->to('organizer/events/' . $id);
    }

    public function moveFieldDown(int $id, int $fieldId)
    {
        if ($this->ownedEvent($id) === null) {
            return redirect()->to('organizer/dashboard')->with('error', 'Event not found.');
        }

        (new EventRegistrationFieldModel())->moveDown($fieldId, $id);

        return redirect()->to('organizer/events/' . $id);
    }

    public function registrationAnswers(int $id, int $registrationId)
    {
        $event = $this->ownedEvent($id);

        if ($event === null) {
            return redirect()->to('organizer/dashboard')->with('error', 'Event not found.');
        }

        $registrationModel = new EventRegistrationModel();
        $registration = $registrationModel->where('event_id', $id)->find($registrationId);

        if ($registration === null) {
            return redirect()->to('organizer/events/' . $id)->with('error', 'Registration not found.');
        }

        $fields = (new EventRegistrationFieldModel())->forEvent($id);
        $values = $registrationModel->decodedCustomFieldValues($registration);

        return view('events/registration_answers', [
            'pageTitle'    => 'Answers — ' . $registration->full_name,
            'event'        => $event,
            'registration' => $registration,
            'fields'       => $fields,
            'values'       => $values,
            'baseUrl'      => 'organizer/events',
            'layout'       => 'organizer/layouts/main',
        ]);
    }

    /** Loads the event only if it belongs to the logged-in organizer — the one ownership check this feature introduces. */
    private function ownedEvent(int $id): ?object
    {
        $event = (new EventModel())->find($id);

        if ($event === null || (int) $event->organizer_id !== (int) session('organizerId')) {
            return null;
        }

        return $event;
    }

    /** Same shape as EventController's identical private method — newline/comma-separated textarea -> JSON-encoded list, or null if blank. */
    private function encodeOptions(?string $raw): ?string
    {
        if (empty(trim((string) $raw))) {
            return null;
        }

        $options = array_values(array_filter(array_map('trim', preg_split('/[\r\n,]+/', $raw)), static fn ($v) => $v !== ''));

        return empty($options) ? null : json_encode($options);
    }
}
