<?php

namespace App\Controllers;

use App\Models\BookingModel;
use App\Models\FolioModel;
use App\Models\FolioPaymentModel;
use App\Models\GuestModel;
use App\Models\RoomModel;
use Config\Lookups;

/**
 * Checkout requires the folio balance to reach zero before the booking is
 * marked checked_out — partial payments can be recorded along the way, but
 * checkout won't finalize until the balance is fully settled. Flagged as
 * an assumption: a real property might want to allow leaving with a
 * residual balance to invoice later.
 */
class CheckOutController extends BaseController
{
    public function index()
    {
        $departures = (new BookingModel())->departuresOn(date('Y-m-d'));

        return view('checkout/index', [
            'pageTitle'    => 'Check-Out',
            'pageSubtitle' => 'Manage guest departures and finalize bills.',
            'departures'   => $departures,
        ]);
    }

    public function form(int $bookingId)
    {
        $booking = (new BookingModel())->withDetails()->where('bookings.id', $bookingId)->first();

        if ($booking === null || $booking->status !== 'checked_in') {
            return redirect()->to('checkout')->with('error', 'Booking not found or not currently checked in.');
        }

        $folios = new FolioModel();
        $folio  = $folios->findForBooking($bookingId);

        return view('checkout/form', [
            'pageTitle'    => 'Check Out',
            'pageSubtitle' => $booking->guest_name . ' — Room ' . $booking->room_number,
            'booking'      => $booking,
            'folio'     => $folio,
            'total'     => $folio ? $folios->totalCharges($folio->id) : '0.00',
            'paid'      => $folio ? $folios->totalPaid($folio->id) : '0.00',
            'balance'   => $folio ? $folios->balanceDue($folio->id) : '0.00',
            'lookups'   => new Lookups(),
        ]);
    }

    public function recordPayment(int $bookingId)
    {
        $booking = (new BookingModel())->find($bookingId);

        if ($booking === null) {
            return redirect()->to('checkout')->with('error', 'Booking not found.');
        }

        $folios = new FolioModel();
        $folio  = $folios->findForBooking($bookingId);

        if ($folio === null) {
            return redirect()->back()->with('error', 'No folio found for this booking.');
        }

        $payments = new FolioPaymentModel();
        $data = [
            'folio_id'    => $folio->id,
            'amount'      => parse_money($this->request->getPost('amount')),
            'method'      => $this->request->getPost('method'),
            'reference'   => null, // no gateway in Phase 1
            'recorded_by' => $this->currentUserId(),
            'paid_at'     => date('Y-m-d H:i:s'),
        ];

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

        $this->logActivity('checkout', "Recorded {$data['method']} payment of " . format_money($data['amount']) . " on folio #{$folio->id}.");

        return redirect()->to('checkout/' . $bookingId)->with('success', 'Payment recorded.');
    }

    public function process(int $bookingId)
    {
        $bookings = new BookingModel();
        $booking  = $bookings->find($bookingId);

        if ($booking === null || $booking->status !== 'checked_in') {
            return redirect()->to('checkout')->with('error', 'Booking not found or not currently checked in.');
        }

        $folios = new FolioModel();
        $folio  = $folios->findForBooking($bookingId);
        $balance = $folio ? $folios->balanceDue($folio->id) : '0.00';

        if ((float) $balance > 0.0) {
            return redirect()->to('checkout/' . $bookingId)->with('error', 'Outstanding balance of ' . format_money($balance) . ' must be settled before checkout.');
        }

        $bookings->update($bookingId, ['status' => 'checked_out']);

        $rooms = new RoomModel();
        $rooms->setStatus($booking->room_id, 'dirty');

        if ($folio) {
            $folios->close($folio->id);
        }

        $this->logActivity('checkout', "Checked out booking #{$bookingId}.");

        $this->sendPostStayFeedbackRequest($booking->guest_id);
        $this->draftPostCheckoutThankYou($bookingId, $folio->id ?? null, $booking->guest_id);

        return redirect()->to('checkout')->with('success', 'Guest checked out. Room marked dirty.');
    }

    /**
     * "Just send the message here — collecting and analyzing the feedback
     * response is a later phase" (Phase 3 brief). No feedback table yet;
     * Phase 4 adds where the guest's reply actually lands.
     */
    private function sendPostStayFeedbackRequest(int $guestId): void
    {
        $guest = (new GuestModel())->find($guestId);

        if ($guest === null) {
            return;
        }

        service('messagingService')->send(
            'post_stay_feedback',
            $guest->id,
            $guest->phone,
            "Hi {$guest->full_name}, thank you for staying with us! We'd love to hear about your experience — please reply and let us know how it was.",
            [$guest->full_name],
        );
    }
    /**
     * Adds a personalized, AI-drafted thank-you into the staff review
     * queue (see GuestMessageDraftController) — separate from and
     * additional to sendPostStayFeedbackRequest() above, which is Phase
     * 3's existing generic feedback-request message and is left exactly
     * as it was: this doesn't replace it, it's a second, more specific
     * message a manager can choose to also send. Drafted from that
     * stay's real folio line items (restaurant/event charges) and real
     * event attendance — never invents an amenity or experience the
     * guest didn't actually have. Auto-sends immediately only if the
     * tenant has opted this category into autosend (default off); the
     * default behavior is queue-for-review only, per the Phase 5 AI
     * brief's guest-facing guardrails.
     */
    private function draftPostCheckoutThankYou(int $bookingId, ?int $folioId, int $guestId): void
    {
        if (service('settings')->get('ai.post_checkout_thankyou_enabled', '0') !== '1') {
            return;
        }

        $guest = (new GuestModel())->find($guestId);

        if ($guest === null || empty($guest->phone)) {
            return;
        }

        $charges = $folioId !== null ? (new \App\Models\FolioLineItemModel())->forFolio($folioId) : [];
        $events  = (new \App\Models\EventModel())->historyForGuest($guestId);

        $data = [
            'guest_name' => $guest->full_name,
            'stay_charges' => array_map(static fn ($c) => ['category' => $c->category, 'description' => $c->description], $charges),
            'event_attendance' => array_map(static fn ($e) => ['event_name' => $e->event_name, 'event_date' => $e->event_date], $events),
        ];

        $systemPrompt = 'You write a short (2-3 sentence) warm, SPECIFIC thank-you SMS to a hotel guest who just '
            . 'checked out. You will be given their real folio charges from this stay and any real event attendance. '
            . 'If the data shows something specific (dined at the restaurant, attended an event, a multi-night stay), '
            . 'reference it naturally — otherwise keep it warm but general. End with a brief, friendly prompt to '
            . 'leave a review. Never invent an amenity, dish, or experience not evidenced by the data given. Return '
            . 'only the message text itself, no greeting placeholder brackets, no quotes.';

        $result = service('claudeService')->chat(
            'post_checkout_thankyou',
            $systemPrompt,
            [['role' => 'user', 'content' => json_encode($data)]],
            [],
            null,
            'booking',
            $bookingId,
            $this->currentUserId(),
        );

        if (! $result['success']) {
            return; // checkout itself already succeeded; a failed draft is not a checkout failure.
        }

        $drafts = new \App\Models\AiMessageDraftModel();
        $draftId = $drafts->insert([
            'category'      => 'post_checkout_thankyou',
            'guest_id'      => $guestId,
            'booking_id'    => $bookingId,
            'to_phone'      => $guest->phone,
            'draft_text'    => trim((string) $result['text'], " \t\n\r\0\x0B\""),
            'status'        => 'pending',
            'data_snapshot' => json_encode($data),
        ]);

        if (service('settings')->get('ai.autosend_post_checkout_thankyou', '0') === '1') {
            \App\Controllers\GuestMessageDraftController::reallySend($drafts->find($draftId), null);
        }
    }
}
