<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Auth;
use App\Csrf;
use App\Pin;
use App\Repositories\Container;

class HubAppointmentsController
{
    public function index(): void
    {
        $status = strtoupper($_GET['status'] ?? 'PENDING');
        $appts  = Container::appointments();
        $list   = $status === 'ALL' ? $appts->all() : $appts->byStatus($status);

        // ARTIST role: filter to only appointments for their linked artist profile
        $me = Auth::user();
        if (($me['role'] ?? '') === 'ARTIST' && !empty($me['artist_profile_id'])) {
            $myArtistId = $me['artist_profile_id'];
            $list = array_values(array_filter($list, fn($a) => ($a['artist_id'] ?? '') === $myArtistId));
        }

        // Enrich with customer + artist records
        $userRepo   = Container::users();
        $artistRepo = Container::artists();
        $enriched = [];
        foreach ($list as $a) {
            $a['_customer'] = !empty($a['customer_id']) ? $userRepo->find($a['customer_id']) : null;
            $a['_artist']   = !empty($a['artist_id'])   ? $artistRepo->find($a['artist_id']) : null;
            $enriched[] = $a;
        }

        // Sort: for pending/approved sort ascending (nearest first); completed/canceled descending
        $desc = in_array($status, ['COMPLETED', 'CANCELED', 'NO_SHOW'], true);
        usort($enriched, function($a, $b) use ($desc) {
            $ta = strtotime($a['start_at'] ?? '0');
            $tb = strtotime($b['start_at'] ?? '0');
            return $desc ? $tb - $ta : $ta - $tb;
        });

        // Group by date
        $grouped = [];
        foreach ($enriched as $a) {
            $day = !empty($a['start_at'])
                ? (new \DateTimeImmutable($a['start_at']))->format('Y-m-d')
                : 'unknown';
            $grouped[$day][] = $a;
        }

        $tabs = ['PENDING', 'APPROVED', 'UPCOMING', 'COMPLETED', 'CANCELED'];
        render('hub', 'hub.appointments', compact('grouped', 'status', 'tabs'), t('hub.appointments.title'));
    }

    public function show(array $params): void
    {
        $appt = Container::appointments()->find($params['id'] ?? '');
        if (!$appt) { http_response_code(404); require MAT_ROOT . '/src/Views/errors/404.php'; return; }
        $customer = !empty($appt['customer_id']) ? Container::users()->find($appt['customer_id']) : null;
        $artist   = !empty($appt['artist_id'])   ? Container::artists()->find($appt['artist_id'])   : null;
        $form     = !empty($appt['intake_form_id']) ? Container::intakeForms()->find($appt['intake_form_id']) : null;
        $artists  = Container::artists()->all(true);
        render('hub', 'hub.appointment-detail', compact('appt', 'customer', 'artist', 'form', 'artists'), $appt['id']);
    }

    public function approve(array $params): void
    {
        Csrf::requireValid();
        $appt = Container::appointments()->find($params['id'] ?? '');
        if (!$appt) { redirect('/hub/appointments'); }
        $staff = Pin::authenticate((string)($_POST['username'] ?? ''), (string)($_POST['pin'] ?? ''));
        if (!$staff) {
            $_SESSION['_flash']['error'] = t('hub.pin.invalid');
            redirect('/hub/appointments/' . $appt['id']);
        }
        $staffName = trim(($staff['first_name'] ?? '') . ' ' . ($staff['last_name'] ?? ''));
        $appt = Container::appointments()->save(array_merge($appt, [
            'status'           => 'APPROVED',
            'approved_by_id'   => $staff['id'],
            'approved_by_name' => $staffName ?: ($staff['username'] ?? 'Staff'),
            'approved_at'      => now_iso(),
        ]));
        Container::audit()->log($staff['id'], 'APPROVE_APPT', 'appointment', $appt['id']);

        // Notify the customer with the confirmation email (include staff notes if any)
        if (!empty($appt['customer_id'])) {
            $cust = Container::users()->find($appt['customer_id']);
            if ($cust && !empty($cust['email'])) {
                \App\Services\Email::bookingApproved($cust, $appt, $appt['notes'] ?? null);
            }
        }

        $_SESSION['_flash']['success'] = t('hub.appointments.approved');
        redirect('/hub/appointments/' . $appt['id']);
    }

    public function saveNotes(array $params): void
    {
        Csrf::requireValid();
        $appt = Container::appointments()->find($params['id'] ?? '');
        if (!$appt) { redirect('/hub/appointments'); }
        $notes = trim((string)($_POST['notes'] ?? ''));
        Container::appointments()->save(array_merge($appt, ['notes' => $notes]));
        $_SESSION['_flash']['success'] = t('hub.appointment.notes_saved');
        redirect('/hub/appointments/' . $appt['id']);
    }

    public function cancel(array $params): void
    {
        Csrf::requireValid();
        $appt = Container::appointments()->find($params['id'] ?? '');
        if (!$appt) { redirect('/hub/appointments'); }
        $staff = Pin::authenticate((string)($_POST['username'] ?? ''), (string)($_POST['pin'] ?? ''));
        if (!$staff) {
            $_SESSION['_flash']['error'] = t('hub.pin.invalid');
            redirect('/hub/appointments/' . $appt['id']);
        }

        $staffName     = trim(($staff['first_name'] ?? '') . ' ' . ($staff['last_name'] ?? ''));
        $cancelReason  = trim((string)($_POST['cancel_reason'] ?? ''));
        $shareWithCust = !empty($_POST['share_reason_with_customer']);

        $appt = Container::appointments()->save(array_merge($appt, [
            'status'           => 'CANCELED',
            'canceled_at'      => now_iso(),
            'canceled_by_id'   => $staff['id'],
            'canceled_by_name' => $staffName ?: ($staff['username'] ?? 'Staff'),
            'cancel_reason'    => $cancelReason,
        ]));
        Container::audit()->log($staff['id'], 'CANCEL_APPT', 'appointment', $appt['id']);

        // Send cancellation emails
        $cust    = !empty($appt['customer_id']) ? Container::users()->find($appt['customer_id']) : null;
        $artist  = !empty($appt['artist_id'])   ? Container::artists()->find($appt['artist_id']) : null;

        // Email customer (with or without reason based on toggle)
        if ($cust && !empty($cust['email'])) {
            \App\Services\Email::appointmentCanceled(
                $cust, $appt, $artist,
                $shareWithCust ? $cancelReason : null
            );
        }

        // Email staff + assigned artist (always includes reason)
        \App\Services\Email::staffCancelAlert(
            $cust, $appt, $artist, $staffName, $cancelReason
        );

        $_SESSION['_flash']['success'] = t('hub.appointments.canceled');
        redirect('/hub/appointments/' . $appt['id']);
    }

    public function complete(array $params): void
    {
        Csrf::requireValid();
        $appt = Container::appointments()->find($params['id'] ?? '');
        if (!$appt) { redirect('/hub/appointments'); }
        $staff = Pin::authenticate((string)($_POST['username'] ?? ''), (string)($_POST['pin'] ?? ''));
        if (!$staff) {
            $_SESSION['_flash']['error'] = t('hub.pin.invalid');
            redirect('/hub/appointments/' . $appt['id']);
        }
        $staffName = trim(($staff['first_name'] ?? '') . ' ' . ($staff['last_name'] ?? ''));
        $appt = Container::appointments()->save(array_merge($appt, [
            'status'            => 'COMPLETED',
            'completed_at'      => now_iso(),
            'completed_by_id'   => $staff['id'],
            'completed_by_name' => $staffName ?: ($staff['username'] ?? 'Staff'),
        ]));
        Container::audit()->log($staff['id'], 'COMPLETE_APPT', 'appointment', $appt['id']);

        // After completion: send aftercare + a copy of the intake form
        if (!empty($appt['customer_id'])) {
            $cust = Container::users()->find($appt['customer_id']);
            $form = !empty($appt['intake_form_id']) ? Container::intakeForms()->find($appt['intake_form_id']) : null;
            if ($cust && !empty($cust['email']) && $form) {
                \App\Services\Email::aftercareAndFormCopy($cust, $appt, $form);
            }
        }

        $_SESSION['_flash']['success'] = t('hub.appointments.completed');
        redirect('/hub/appointments/' . $appt['id']);
    }

    /**
     * Staff proposes a new time for an existing appointment.
     * Saves proposed_start_at/proposed_end_at + reschedule_token on the appointment,
     * sends the customer an email to approve or reject.
     */
    public function reschedule(array $params): void
    {
        Csrf::requireValid();
        $appt = Container::appointments()->find($params['id'] ?? '');
        if (!$appt) { redirect('/hub/appointments'); }

        $staff = Pin::authenticate((string)($_POST['username'] ?? ''), (string)($_POST['pin'] ?? ''));
        if (!$staff) {
            $_SESSION['_flash']['error'] = t('hub.pin.invalid');
            redirect('/hub/appointments/' . $appt['id']);
        }

        $dateStr = trim((string)($_POST['new_date'] ?? ''));
        $timeStr = trim((string)($_POST['new_time'] ?? ''));
        if (!$dateStr || !$timeStr) {
            $_SESSION['_flash']['error'] = t('hub.appointment.reschedule_missing');
            redirect('/hub/appointments/' . $appt['id']);
        }

        $newStart = date('Y-m-d\TH:i:s', strtotime($dateStr . ' ' . $timeStr));
        $newEnd   = date('Y-m-d\TH:i:s', strtotime($newStart) + 1800); // 30-min slot

        // Conflict check for the proposed new time
        $artistId = $appt['artist_id'] ?? '';
        if ($artistId) {
            $conflict = \App\Services\Availability::findConflict($artistId, $newStart, $newEnd, $appt['id']);
            if ($conflict) {
                $_SESSION['_flash']['error'] = t('booking.errors.slot_taken');
                redirect('/hub/appointments/' . $appt['id']);
            }
        }

        $token = uuid();
        $appt = Container::appointments()->save(array_merge($appt, [
            'proposed_start_at' => $newStart,
            'proposed_end_at'   => $newEnd,
            'reschedule_token'  => $token,
            'reschedule_reason' => trim((string)($_POST['reason'] ?? '')),
        ]));
        Container::audit()->log($staff['id'], 'PROPOSE_RESCHEDULE', 'appointment', $appt['id']);

        // Send customer email
        if (!empty($appt['customer_id'])) {
            $cust = Container::users()->find($appt['customer_id']);
            if ($cust && !empty($cust['email'])) {
                $scheme = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http';
                $host   = $_SERVER['HTTP_HOST'] ?? 'localhost';
                $base   = $scheme . '://' . $host;
                \App\Services\Email::rescheduleProposal($cust, $appt, $base);
            }
        }

        $_SESSION['_flash']['success'] = t('hub.appointment.reschedule_sent');
        redirect('/hub/appointments/' . $appt['id']);
    }
}
