<?php
declare(strict_types=1);

namespace App\Services;

use App\Repositories\Container;

/**
 * Booking workflow helpers: validation, draft upsert, final submission.
 */
class Booking
{
    /** Create or update a DRAFT appointment + intake form from wizard session state. */
    public static function saveDraft(array $state): array
    {
        $appts = Container::appointments();
        $intake = Container::intakeForms();

        // Upsert intake form first (holds the general info + resume token)
        $form = [];
        if (!empty($state['intake_form_id'])) {
            $existing = $intake->find($state['intake_form_id']);
            if ($existing) $form = $existing;
        }
        $form['status'] = $form['status'] ?? 'DRAFT';
        $form['general_info'] = array_merge((array)($form['general_info'] ?? []), (array)($state['general_info'] ?? []));
        $form['medical_conditions'] = $state['medical_conditions'] ?? ($form['medical_conditions'] ?? []);
        $form['medical_other']      = $state['medical_other']      ?? ($form['medical_other'] ?? null);
        $form['on_medication']      = $state['on_medication']      ?? ($form['on_medication'] ?? null);
        $form['medication_notes']   = $state['medication_notes']   ?? ($form['medication_notes'] ?? null);
        $form['tattoo_details']     = $state['tattoo_details']     ?? ($form['tattoo_details'] ?? null);
        $form = $intake->save($form);

        // Upsert appointment
        $appt = [];
        if (!empty($state['appointment_id'])) {
            $existing = $appts->find($state['appointment_id']);
            if ($existing) $appt = $existing;
        }
        $appt['customer_id']   = $state['customer_id']   ?? ($appt['customer_id']   ?? null);
        $appt['artist_id']     = $state['artist_id']     ?? ($appt['artist_id']     ?? null);
        $appt['start_at']      = $state['start_at']      ?? ($appt['start_at']      ?? null);
        $appt['end_at']        = $state['end_at']        ?? ($appt['end_at']        ?? null);
        $appt['status']        = $appt['status'] ?? 'PENDING';
        $appt['source']        = 'ONLINE';
        $appt['intake_form_id'] = $form['id'];
        $appt = $appts->save($appt);

        return ['appointment' => $appt, 'intake_form' => $form];
    }

    /**
     * Finalize a booking: upsert customer record from general_info, link everything.
     * Throws \RuntimeException if the slot is already taken (race condition guard).
     */
    public static function submit(array $state): array
    {
        $users  = Container::users();
        $appts  = Container::appointments();
        $intake = Container::intakeForms();

        // Server-side conflict guard — reject if slot was taken between page load and submit
        $artistId = $state['artist_id'] ?? null;
        $startAt  = $state['start_at']  ?? null;
        $endAt    = $state['end_at']    ?? null;
        if ($artistId && $startAt && $endAt) {
            $conflict = Availability::findConflict($artistId, $startAt, $endAt, $state['appointment_id'] ?? null);
            if ($conflict) {
                throw new \RuntimeException('SLOT_TAKEN');
            }
        }

        $info = (array)($state['general_info'] ?? []);

        // Find or create the customer user
        $customer = null;
        if (!empty($info['email']))  $customer = $users->findByEmail($info['email']);
        if (!$customer && !empty($info['phone'])) $customer = $users->findByPhone($info['phone']);

        $customer = $users->save(array_merge($customer ?? [], [
            'role'       => 'CUSTOMER',
            'email'      => $info['email']      ?? ($customer['email']      ?? null),
            'phone'      => $info['phone']      ?? ($customer['phone']      ?? null),
            'first_name' => $info['first_name'] ?? ($customer['first_name'] ?? ''),
            'last_name'  => $info['last_name']  ?? ($customer['last_name']  ?? ''),
            'address_line' => $info['address']  ?? ($customer['address_line'] ?? null),
            'city'       => $info['city']       ?? ($customer['city']       ?? null),
            'state'      => $info['state']      ?? ($customer['state']      ?? null),
            'zip'        => $info['zip']        ?? ($customer['zip']        ?? null),
            'date_of_birth' => $info['date_of_birth'] ?? ($customer['date_of_birth'] ?? null),
            'is_active'  => true,
        ]));

        // Persist draft first so it has an id
        $draft = self::saveDraft(array_merge($state, ['customer_id' => $customer['id']]));
        $form = $draft['intake_form'];
        $appt = $draft['appointment'];

        // Mark intake form with customer + status SUBMITTED (still needs signing)
        $form = $intake->save(array_merge($form, [
            'customer_id' => $customer['id'],
            'status' => 'SUBMITTED',
        ]));

        $appt = $appts->save(array_merge($appt, [
            'customer_id' => $customer['id'],
            'intake_form_id' => $form['id'],
            'status' => 'PENDING',
        ]));

        return ['customer' => $customer, 'appointment' => $appt, 'intake_form' => $form];
    }

    public static function isAdult(?string $dob): bool
    {
        if (!$dob) return false;
        try {
            $d = new \DateTimeImmutable($dob);
        } catch (\Exception $e) { return false; }
        $now = new \DateTimeImmutable('now');
        return $d->diff($now)->y >= 18;
    }
}
