<?php

namespace App\Controllers;

use App\Models\EventOrganizerModel;
use App\Models\EventOrganizerPasswordCodeModel;
use Throwable;

/**
 * Serves BOTH the first-time invite (staff generate the code from their
 * own session via EventController::inviteOrganizer() and text the
 * organizer a link — no self-service "request" step needed, staff
 * already have the contact details) and the organizer's own ongoing
 * forgot-password (this controller's requestCode()).
 *
 * Unlike ForgotPasswordController, the "set password" step here is
 * IDENTIFIER-based (the organizer re-enters their email alongside the
 * code), not session-gated — ForgotPasswordController's session-gating
 * works because request-and-verify always happen in the same browser
 * session, but an invited organizer opens their SMS link cold, with no
 * session continuity from whatever staff member generated it. Once the
 * verify step doesn't depend on a prior session, both entry points can
 * share the exact same form/handler.
 */
class EventOrganizerPasswordController extends BaseController
{
    public function showRequestForm()
    {
        return view('organizer/auth/forgot_password', ['pageTitle' => 'Forgot Password']);
    }

    public function requestCode()
    {
        $email      = trim((string) $this->request->getPost('email'));
        $organizers = new EventOrganizerModel();
        $organizer  = $organizers->where('email', $email)->where('is_active', 1)->first();

        // Same generic message whether or not the email matches an
        // account, so this can't be used to enumerate organizer emails.
        $genericMessage = 'If that email has an organizer account with a phone number on file, we\'ve sent a code by SMS.';

        if ($organizer === null || empty($organizer->phone)) {
            return redirect()->to('organizer/login')->with('success', $genericMessage);
        }

        $this->sendCode($organizer, 'Your MaxYields event organizer password code is {code}. It expires in 10 minutes. If you didn\'t request this, ignore this message.');

        return redirect()->to('organizer/set-password?email=' . urlencode($email))->with('success', $genericMessage);
    }

    public function showSetPasswordForm()
    {
        return view('organizer/auth/set_password', [
            'pageTitle' => 'Set Password',
            'email'     => $this->request->getGet('email') ?: '',
        ]);
    }

    public function resendCode()
    {
        $email     = trim((string) $this->request->getPost('email'));
        $organizer = (new EventOrganizerModel())->findByEmail($email);

        if ($organizer !== null && ! empty($organizer->phone)) {
            $this->sendCode($organizer, 'Your MaxYields event organizer password code is {code}. It expires in 10 minutes.');
        }

        return redirect()->to('organizer/set-password?email=' . urlencode($email))->with('success', 'If that email has an account, a new code has been sent.');
    }

    public function setPassword()
    {
        $email       = trim((string) $this->request->getPost('email'));
        $code        = trim((string) $this->request->getPost('code'));
        $newPassword = (string) $this->request->getPost('password');
        $confirm     = (string) $this->request->getPost('password_confirm');

        $organizers = new EventOrganizerModel();
        $organizer  = $organizers->findByEmail($email);

        if ($organizer === null) {
            return redirect()->back()->withInput()->with('error', 'That code is invalid or has expired. Request a new one.');
        }

        $codes = new EventOrganizerPasswordCodeModel();

        if (! $codes->isValid($organizer->id, $code)) {
            return redirect()->back()->withInput()->with('error', 'That code is invalid or has expired. Request a new one.');
        }

        if (strlen($newPassword) < 8) {
            return redirect()->back()->withInput()->with('error', 'Password must be at least 8 characters.');
        }

        if ($newPassword !== $confirm) {
            return redirect()->back()->withInput()->with('error', 'Passwords do not match.');
        }

        $organizers->skipValidation(true)->update($organizer->id, [
            'password_hash' => password_hash($newPassword, PASSWORD_DEFAULT),
            'is_active'     => 1,
        ]);
        $codes->consume($organizer->id, $code);

        $this->logActivity('events', "Organizer {$organizer->full_name} set their password.");

        return redirect()->to('organizer/login')->with('success', 'Password set — you can now log in.');
    }

    private function sendCode(object $organizer, string $template): void
    {
        $code = (new EventOrganizerPasswordCodeModel())->generateFor($organizer->id);
        $body = str_replace('{code}', $code, $template);

        try {
            service('hubtelService')->sendSms($organizer->phone, $body);
        } catch (Throwable $e) {
            log_message('error', 'Event organizer password SMS failed: ' . $e->getMessage());
        }
    }
}
