<?php

namespace App\Controllers;

use App\Models\ActivityLogModel;
use App\Models\AiAlertModel;
use App\Models\AiDailyBriefingModel;
use App\Models\BookingModel;
use App\Models\EventModel;
use App\Models\FolioLineItemModel;
use App\Models\FolioPaymentModel;
use App\Models\RoomModel;
use App\Models\RoomTypeModel;
use Config\Lookups;

/**
 * Redesigned to match the user-supplied "Hotel Dashboard" mockup. Every
 * figure here comes from real data already tracked by Phases 1-3 — see
 * the model methods added alongside this rewrite (BookingModel::
 * occupiedRoomCountOn/reservationsOverview, FolioLineItemModel::
 * totalBetween/byCategoryBetween, FolioPaymentModel::totalBetween,
 * RoomTypeModel::occupancyBreakdown, EventModel::countOn,
 * ActivityLogModel::recent) rather than any placeholder/fabricated
 * numbers. The mockup's Housekeeping/Maintenance/Inventory widgets are
 * NOT modules that exist yet (Phase 4) — per the user's explicit choice,
 * those are represented in the nav (layouts/main.php) as disabled
 * "coming soon" items rather than being faked here.
 */
class DashboardController extends BaseController
{
    public function index()
    {
        $bookings  = new BookingModel();
        $rooms     = new RoomModel();
        $roomTypes = new RoomTypeModel();
        $lineItems = new FolioLineItemModel();
        $payments  = new FolioPaymentModel();
        $events    = new EventModel();

        $today     = date('Y-m-d');
        $yesterday = date('Y-m-d', strtotime('-1 day'));

        $totalRooms = $rooms->countAllResults();

        $roomStatusCounts = [];
        foreach (array_keys((new Lookups())->roomStatuses) as $status) {
            $roomStatusCounts[$status] = $rooms->where('status', $status)->countAllResults();
        }

        $occupiedToday  = $roomStatusCounts['occupied'] ?? 0;
        $occupancyToday = $totalRooms > 0 ? (int) round($occupiedToday / $totalRooms * 100) : 0;

        // 7-day occupancy trend: today uses the live room-status count
        // above (a `confirmed` booking checking in later today hasn't
        // occupied the room yet); every prior day is reconstructed from
        // booking date ranges, since we don't keep a historical snapshot
        // table (see BookingModel::occupiedRoomCountOn for why that's
        // still an accurate real figure, not an approximation dressed up).
        $occupancyTrend = [];
        for ($i = 6; $i >= 0; $i--) {
            $date = date('Y-m-d', strtotime("-{$i} days"));
            $count = $i === 0 ? $occupiedToday : $bookings->occupiedRoomCountOn($date);
            $occupancyTrend[] = [
                'date' => $date,
                'pct'  => $totalRooms > 0 ? (int) round($count / $totalRooms * 100) : 0,
            ];
        }

        $revenueToday     = $lineItems->totalOn($today);
        $revenueYesterday = $lineItems->totalOn($yesterday);
        $revenueChangePct = $this->percentChange($revenueYesterday, $revenueToday);

        $categoryToday = $lineItems->byCategoryOn($today);
        $roomRevenue   = $categoryToday['room_charge'] ?? '0.00';
        $fnbRevenue    = $categoryToday['restaurant'] ?? '0.00';
        $otherRevenue  = money_add($categoryToday['event'] ?? '0.00', $categoryToday['other'] ?? '0.00');

        $monthStart = date('Y-m-01');

        return view('dashboard/index', [
            'pageTitle'         => 'Hotel Dashboard',
            'pageSubtitle'      => 'Welcome back, ' . (session('userName') ?? 'there') . "! Here's what's happening at your hotel today.",
            'totalRooms'        => $totalRooms,
            'occupiedToday'     => $occupiedToday,
            'occupancyToday'    => $occupancyToday,
            // occupancyTrend[5] is yesterday (index 6 - 1; index 6 is today) — see the loop above.
            'occupancyChangePct'=> $this->percentChange($occupancyTrend[5]['pct'], $occupancyToday),
            'occupancyTrend'    => $occupancyTrend,
            'roomStatusCounts'  => $roomStatusCounts,
            'arrivalsToday'     => $bookings->arrivalsOn($today),
            'departuresToday'   => $bookings->departuresOn($today),
            'inHouseGuests'     => $bookings->where('status', 'checked_in')->countAllResults(),
            'revenueToday'      => $revenueToday,
            'revenueChangePct'  => $revenueChangePct,
            'roomRevenue'       => $roomRevenue,
            'fnbRevenue'        => $fnbRevenue,
            'otherRevenue'      => $otherRevenue,
            'monthCollected'    => $payments->totalBetween($monthStart, $today),
            'reservations'      => $bookings->reservationsOverview($monthStart, date('Y-m-t')),
            'roomTypeOccupancy' => $roomTypes->occupancyBreakdown(),
            'eventsToday'       => $events->countOn($today),
            'recentActivity'    => (new ActivityLogModel())->recent(6),
            'dailyBriefing'     => (new AiDailyBriefingModel())->today(),
            'dailyBriefingEnabled' => service('settings')->get('ai.daily_briefing_enabled', '1') === '1',
            'openAlertsCount'   => service('settings')->get('ai.anomaly_flagging_enabled', '1') === '1' ? (new AiAlertModel())->countOpen() : 0,
        ]);
    }

    /**
     * "Generate Briefing" on the dashboard card — same
     * DailyBriefingService::generateForCurrentTenant() the ai:daily-
     * briefing scheduled command uses, called on-demand here since this
     * dev environment has no real cron running it automatically yet.
     * Defaults to returning today's briefing if one already exists
     * (idempotent, same as the command); `regenerate=1` forces a fresh
     * Claude call, for a manager who wants an updated take later in the
     * day after real data has changed.
     */
    public function generateBriefing()
    {
        if (service('settings')->get('ai.daily_briefing_enabled', '1') !== '1') {
            return $this->response->setJSON(['success' => false, 'error' => 'Daily Briefing is turned off — enable it under Settings > AI Features.', 'csrf_hash' => csrf_hash()]);
        }

        $force  = $this->request->getPost('regenerate') === '1';
        $result = service('dailyBriefingService')->generateForCurrentTenant($this->currentUserId(), $force);

        if (! $result['success']) {
            return $this->response->setJSON(['success' => false, 'error' => $result['error'], 'csrf_hash' => csrf_hash()]);
        }

        $this->logActivity('dashboard', 'Generated the AI daily briefing for ' . $result['briefing']->briefing_date . '.');

        return $this->response->setJSON(['success' => true, 'text' => $result['briefing']->summary_text, 'csrf_hash' => csrf_hash()]);
    }

    private function percentChange(float|string $previous, float|string $current): float
    {
        $previous = (float) $previous;
        $current  = (float) $current;

        if ($previous == 0.0) {
            return $current > 0 ? 100.0 : 0.0;
        }

        return round((($current - $previous) / $previous) * 100, 1);
    }
}
