<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Csrf;
use App\Repositories\Container;
use App\Services\Booking;
use App\Services\Email;

class BookingController
{
    private const TOTAL_STEPS = 6;

    /** Absolute URL so email links still work even when base_url isn't set. */
    private static function absoluteUrl(string $path): string
    {
        $scheme = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http';
        $host = $_SERVER['HTTP_HOST'] ?? 'localhost';
        return $scheme . '://' . $host . (str_starts_with($path, '/') ? $path : '/' . $path);
    }

    public function start(): void
    {
        // Fresh wizard state unless resuming
        if (!isset($_SESSION['booking'])) {
            $_SESSION['booking'] = [
                'step' => 1,
                'artist_id' => $_GET['artist'] ?? null,
                'general_info' => [],
                'medical_conditions' => [],
            ];
        }
        redirect('/book/step/1');
    }

    public function step(array $params): void
    {
        $n = max(1, min(self::TOTAL_STEPS, (int)($params['n'] ?? 1)));
        $state = $_SESSION['booking'] ?? [];
        $state['step'] = $n;
        $_SESSION['booking'] = $state;

        $artists = Container::artists()->all(true);
        render('public', 'booking.step-' . $n, compact('state', 'artists'), t('booking.step_' . $n . '.title'));
    }

    public function saveStep(array $params): void
    {
        Csrf::requireValid();
        $n = max(1, min(self::TOTAL_STEPS, (int)($params['n'] ?? 1)));
        $state = $_SESSION['booking'] ?? [];

        switch ($n) {
            case 1:
                $state['artist_id'] = ($_POST['artist_id'] ?? '') ?: null;
                break;
            case 2:
                $state['start_at'] = $_POST['start_at'] ?? null;
                $state['end_at']   = $_POST['end_at']   ?? null;
                if (empty($state['start_at'])) {
                    $_SESSION['_flash']['error'] = t('booking.errors.pick_slot');
                    redirect('/book/step/2');
                }
                break;
            case 3:
                $state['general_info'] = array_merge($state['general_info'] ?? [], [
                    'first_name' => trim((string)($_POST['first_name'] ?? '')),
                    'last_name'  => trim((string)($_POST['last_name'] ?? '')),
                    'email'      => trim((string)($_POST['email'] ?? '')),
                    'phone'      => trim((string)($_POST['phone'] ?? '')),
                    'address'    => trim((string)($_POST['address'] ?? '')),
                    'city'       => trim((string)($_POST['city'] ?? '')),
                    'state'      => trim((string)($_POST['state'] ?? '')),
                    'zip'        => trim((string)($_POST['zip'] ?? '')),
                ]);
                foreach (['first_name','last_name','email','phone'] as $req) {
                    if (empty($state['general_info'][$req])) {
                        $_SESSION['_flash']['error'] = t('booking.errors.required_info');
                        $_SESSION['booking'] = $state;
                        redirect('/book/step/3');
                    }
                }
                break;
            case 4:
                $state['general_info']['date_of_birth'] = $_POST['date_of_birth'] ?? null;
                $state['general_info']['over_18']       = !empty($_POST['over_18']);
                if (!$state['general_info']['over_18'] && empty($_POST['guardian_ack'])) {
                    $_SESSION['_flash']['error'] = t('booking.errors.guardian_required');
                    $_SESSION['booking'] = $state;
                    redirect('/book/step/4');
                }
                break;
            case 5:
                $state['tattoo_details'] = [
                    'description' => trim((string)($_POST['description'] ?? '')),
                    'size'        => trim((string)($_POST['size'] ?? '')),
                    'placement'   => trim((string)($_POST['placement'] ?? '')),
                    'reference_image_url' => $_POST['reference_image_url'] ?? null,
                ];
                break;
            case 6:
                // review step -> submit
                $_SESSION['booking'] = $state;
                redirect('/book/submit');
        }

        $_SESSION['booking'] = $state;
        // Persist draft to storage so the resume link works even if the session dies
        Booking::saveDraft($state + [
            'appointment_id' => $state['appointment_id'] ?? null,
            'intake_form_id' => $state['intake_form_id'] ?? null,
        ]);
        $draft = Booking::saveDraft($state);
        $_SESSION['booking']['appointment_id'] = $draft['appointment']['id'] ?? null;
        $_SESSION['booking']['intake_form_id'] = $draft['intake_form']['id'] ?? null;

        $next = min(self::TOTAL_STEPS, $n + 1);
        redirect('/book/step/' . $next);
    }

    public function review(): void
    {
        $state = $_SESSION['booking'] ?? null;
        if (!$state) { redirect('/book'); }
        render('public', 'booking.review', compact('state'), t('booking.review.title'));
    }

    public function submit(): void
    {
        $state = $_SESSION['booking'] ?? null;
        if (!$state) { redirect('/book'); }

        try {
            $result = Booking::submit($state);
        } catch (\RuntimeException $e) {
            if ($e->getMessage() === 'SLOT_TAKEN') {
                $_SESSION['_flash']['error'] = t('booking.errors.slot_taken');
                redirect('/book/step/2');
            }
            throw $e;
        }

        // Customer email: link to the public intake form page
        $intakeUrl = self::absoluteUrl('/intake/' . rawurlencode($result['intake_form']['resume_token'] ?? ''));
        Email::bookingRequested($result['customer'], $result['appointment'], $intakeUrl);

        // Staff alert: separate branded email with customer details + hub deep link
        $artist = !empty($result['appointment']['artist_id'])
            ? \App\Repositories\Container::artists()->find($result['appointment']['artist_id'])
            : null;
        $hubUrl = self::absoluteUrl('/hub/appointments/' . ($result['appointment']['id'] ?? ''));
        Email::staffNewBookingAlert($result['customer'], $result['appointment'], $artist, $hubUrl);

        unset($_SESSION['booking']);
        redirect('/book/confirm/' . $result['appointment']['id']);
    }

    public function confirm(array $params): void
    {
        $appt = Container::appointments()->find($params['id'] ?? '');
        if (!$appt) { redirect('/'); }
        $customer = $appt['customer_id'] ? Container::users()->find($appt['customer_id']) : null;
        $form = $appt['intake_form_id'] ? Container::intakeForms()->find($appt['intake_form_id']) : null;
        render('public', 'booking.confirm', compact('appt', 'customer', 'form'), t('booking.confirm.title'));
    }

    public function resume(): void
    {
        $token = $_GET['token'] ?? '';
        $form = Container::intakeForms()->findByResumeToken($token);
        if (!$form) {
            $_SESSION['_flash']['error'] = t('booking.errors.resume_not_found');
            redirect('/book');
        }
        // Rehydrate wizard state from form + linked appointment
        $appts = Container::appointments();
        $linked = null;
        foreach ($appts->all() as $a) {
            if (($a['intake_form_id'] ?? null) === $form['id']) { $linked = $a; break; }
        }
        $_SESSION['booking'] = [
            'step' => 3,
            'appointment_id' => $linked['id'] ?? null,
            'intake_form_id' => $form['id'],
            'artist_id' => $linked['artist_id'] ?? null,
            'start_at'  => $linked['start_at'] ?? null,
            'end_at'    => $linked['end_at']   ?? null,
            'general_info' => (array)($form['general_info'] ?? []),
            'medical_conditions' => (array)($form['medical_conditions'] ?? []),
            'medical_other' => $form['medical_other'] ?? null,
            'on_medication' => $form['on_medication'] ?? null,
            'medication_notes' => $form['medication_notes'] ?? null,
            'tattoo_details' => (array)($form['tattoo_details'] ?? []),
        ];
        $_SESSION['_flash']['success'] = t('booking.resumed');
        redirect('/book/step/3');
    }
}
