<?php

namespace App\Controllers;

use App\Libraries\Settings;
use App\Models\BookingModel;
use App\Models\FolioLineItemModel;
use App\Models\MaintenanceWorkOrderModel;
use App\Models\RoomModel;
use App\Models\RoomTypeModel;

/**
 * "AI Modules" — the user-supplied mockup showed Demand Forecast/Dynamic
 * Pricing/Guest Insights/Anomaly Detection cards, an "AI Performance"
 * score, AI Recommendations, Quick AI Actions, and AI Usage stats
 * (queries, reports generated, time saved). None of that is real: there
 * is no ML model, no forecasting engine, no usage tracking, and no
 * guest-satisfaction/review data to build "Guest Insights" or "Anomaly
 * Detection" from. Rather than fabricate a fake AI system (a working-
 * looking "87% System Optimization" score with nothing behind it, usage
 * counters that were never counting anything), this page shows a small
 * number of real, rule-based/statistical observations computed directly
 * from operational data — clearly labeled as that, not as machine
 * learning — and nothing else from the mockup. "Guest Satisfaction Risk"
 * was dropped entirely: there's no review/feedback data in this schema
 * to compute it from at all.
 *
 * "AI Module Settings" (also in the mockup batch — confidence thresholds,
 * auto-notifications) is handled the same honest way: each insight below
 * has one real on/off toggle and, where relevant, one real numeric
 * threshold that actually drives its own rule (see settings()/
 * updateSettings() and the ai.* keys in Settings) — never a fake
 * "confidence %" slider with nothing behind it.
 */
class AiInsightsController extends BaseController
{
    public function index()
    {
        $settings = service('settings');

        return view('ai_insights/index', [
            'pageTitle'    => 'Insights',
            'pageSubtitle' => 'Automated, rule-based observations computed from your real operational data.',
            'insights'     => array_filter([
                $this->occupancyTrendInsight($settings),
                $this->pricingOpportunityInsight($settings),
                $this->maintenanceInsight($settings),
                $this->weekdayVsWeekendInsight($settings),
            ]),
        ]);
    }

    /**
     * Real settings, not fake AI tuning: each toggle actually skips that
     * insight's computation entirely (not just hides the card), and each
     * threshold is the exact number the corresponding rule above compares
     * against — changing it here changes what triggers, verifiably.
     */
    public function settings()
    {
        $settings = service('settings');

        return view('ai_insights/settings', [
            'pageTitle'    => 'AI Module Settings',
            'pageSubtitle' => 'Toggle which rule-based observations run, and tune the thresholds behind them.',
            'values'       => [
                'ai.occupancy_trend_enabled'      => $settings->get('ai.occupancy_trend_enabled', '1'),
                'ai.occupancy_trend_threshold'    => $settings->get('ai.occupancy_trend_threshold', '15'),
                'ai.pricing_opportunity_enabled'  => $settings->get('ai.pricing_opportunity_enabled', '1'),
                'ai.pricing_opportunity_threshold' => $settings->get('ai.pricing_opportunity_threshold', '85'),
                'ai.maintenance_backlog_enabled'  => $settings->get('ai.maintenance_backlog_enabled', '1'),
                'ai.weekend_demand_enabled'       => $settings->get('ai.weekend_demand_enabled', '1'),
            ],
        ]);
    }

    public function updateSettings()
    {
        $settings = service('settings');

        $settings->set('ai.occupancy_trend_enabled', $this->request->getPost('occupancy_trend_enabled') ? '1' : '0');
        $settings->set('ai.pricing_opportunity_enabled', $this->request->getPost('pricing_opportunity_enabled') ? '1' : '0');
        $settings->set('ai.maintenance_backlog_enabled', $this->request->getPost('maintenance_backlog_enabled') ? '1' : '0');
        $settings->set('ai.weekend_demand_enabled', $this->request->getPost('weekend_demand_enabled') ? '1' : '0');

        $occThreshold = (int) $this->request->getPost('occupancy_trend_threshold');
        $priceThreshold = (int) $this->request->getPost('pricing_opportunity_threshold');

        $settings->set('ai.occupancy_trend_threshold', (string) max(1, min(100, $occThreshold ?: 15)));
        $settings->set('ai.pricing_opportunity_threshold', (string) max(1, min(100, $priceThreshold ?: 85)));

        $this->logActivity('settings', 'Updated AI module settings.');

        return redirect()->to('ai-modules/settings')->with('success', 'AI module settings saved.');
    }

    /**
     * Compares this week's average occupancy to last week's — a plain
     * before/after comparison over real daily occupancy figures, not a
     * forecast of anything future.
     */
    private function occupancyTrendInsight(Settings $settings): ?array
    {
        if ($settings->get('ai.occupancy_trend_enabled', '1') === '0') {
            return null;
        }

        $bookings   = new BookingModel();
        $totalRooms = (new RoomModel())->countAllResults();

        if ($totalRooms === 0) {
            return null;
        }

        $thisWeek = $this->avgOccupancy($bookings, $totalRooms, 0, 6);
        $lastWeek = $this->avgOccupancy($bookings, $totalRooms, 7, 13);

        if ($lastWeek == 0.0) {
            return null;
        }

        $change    = round((($thisWeek - $lastWeek) / $lastWeek) * 100, 1);
        $threshold = (int) $settings->get('ai.occupancy_trend_threshold', '15');

        return [
            'title'    => 'Occupancy Trend',
            'severity' => abs($change) >= $threshold ? 'high' : 'medium',
            'summary'  => "Occupancy is " . ($change >= 0 ? 'up' : 'down') . ' ' . abs($change) . '% this week (' . $thisWeek . '%) compared to last week (' . $lastWeek . '%).',
            'basis'    => "Based on real occupied-room counts for the last 14 days — flagged \"high\" at \u{2265}{$threshold}% change (set under AI Module Settings).",
        ];
    }

    private function avgOccupancy(BookingModel $bookings, int $totalRooms, int $startDaysAgo, int $endDaysAgo): float
    {
        $total = 0;
        $count = 0;

        for ($i = $startDaysAgo; $i <= $endDaysAgo; $i++) {
            $date = date('Y-m-d', strtotime("-{$i} days"));
            $occupied = $i === 0 ? (new RoomModel())->where('status', 'occupied')->countAllResults() : $bookings->occupiedRoomCountOn($date);
            $total += $totalRooms > 0 ? ($occupied / $totalRooms * 100) : 0;
            $count++;
        }

        return $count > 0 ? round($total / $count, 1) : 0.0;
    }

    /**
     * Flags any room type currently running hot (>= the configured
     * threshold, default 85% of its rooms occupied right now) as worth a
     * rate review — a plain threshold rule against real live occupancy,
     * not a pricing algorithm.
     */
    private function pricingOpportunityInsight(Settings $settings): ?array
    {
        if ($settings->get('ai.pricing_opportunity_enabled', '1') === '0') {
            return null;
        }

        $threshold = (int) $settings->get('ai.pricing_opportunity_threshold', '85');
        $breakdown = (new RoomTypeModel())->occupancyBreakdown();
        $hot       = array_filter($breakdown, static fn ($t) => $t->pct >= $threshold);

        if (empty($hot)) {
            return null;
        }

        $names = implode(', ', array_map(static fn ($t) => $t->name . ' (' . $t->pct . '%)', $hot));

        return [
            'title'    => 'Pricing Opportunity',
            'severity' => 'medium',
            'summary'  => "Running near full occupancy right now: {$names}. Consider reviewing rates for these room types.",
            'basis'    => "Rule: room type currently \u{2265}{$threshold}% occupied (set under AI Module Settings) — a threshold check, not a pricing model.",
        ];
    }

    /**
     * Real count of overdue/open maintenance work orders — substituted
     * for the mockup's "Maintenance Prediction" (which implied predicting
     * future equipment failure, not something this app can do).
     */
    private function maintenanceInsight(Settings $settings): ?array
    {
        if ($settings->get('ai.maintenance_backlog_enabled', '1') === '0') {
            return null;
        }

        $overdue = (new MaintenanceWorkOrderModel())->countOverdue();
        $open    = (new MaintenanceWorkOrderModel())->countByStatus('open');

        if ($overdue === 0 && $open === 0) {
            return null;
        }

        return [
            'title'    => 'Maintenance Backlog',
            'severity' => $overdue > 0 ? 'high' : 'low',
            'summary'  => $overdue > 0
                ? "{$overdue} maintenance work order(s) are overdue, {$open} open in total."
                : "{$open} open maintenance work order(s), none overdue.",
            'basis'    => 'Real count from the Maintenance module — not a failure prediction.',
        ];
    }

    /**
     * Real statistical comparison: average daily F&B revenue on weekends
     * vs weekdays over the last 4 weeks.
     */
    private function weekdayVsWeekendInsight(Settings $settings): ?array
    {
        if ($settings->get('ai.weekend_demand_enabled', '1') === '0') {
            return null;
        }

        $lineItems = new FolioLineItemModel();
        $weekend   = [];
        $weekday   = [];

        for ($i = 0; $i < 28; $i++) {
            $date = date('Y-m-d', strtotime("-{$i} days"));
            $dow  = (int) date('N', strtotime($date));
            $cat  = $lineItems->byCategoryOn($date);
            $amount = (float) ($cat['restaurant'] ?? 0);

            if ($dow >= 6) {
                $weekend[] = $amount;
            } else {
                $weekday[] = $amount;
            }
        }

        $avgWeekend = count($weekend) > 0 ? array_sum($weekend) / count($weekend) : 0;
        $avgWeekday = count($weekday) > 0 ? array_sum($weekday) / count($weekday) : 0;

        if ($avgWeekday == 0.0 && $avgWeekend == 0.0) {
            return null;
        }

        $diff = $avgWeekday > 0 ? round((($avgWeekend - $avgWeekday) / $avgWeekday) * 100, 1) : 0;

        return [
            'title'    => 'F&B Weekend Demand',
            'severity' => 'low',
            'summary'  => 'Average daily F&B revenue on weekends is ' . ($diff >= 0 ? abs($diff) . '% higher' : abs($diff) . '% lower') . ' than weekdays, based on the last 4 weeks.',
            'basis'    => 'Real folio charges, category "restaurant" — a statistical average, not a forecast.',
        ];
    }
}
