<?php
declare(strict_types=1);

namespace App\Modules\FacilityDashboards\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;

class FacilityDashboardController extends Controller
{
    public function show(Request $request, string $id): Response
    {
        $this->authorize('facility.dashboard');
        $db = App::getInstance()->db();

        $facility = $db->selectOne("SELECT * FROM facilities WHERE id = ? AND is_archived = 0", [(int) $id]);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $today = date('Y-m-d');
        $filterMode = trim((string) $request->get('filter', 'day'));
        $dateFrom = trim((string) $request->get('date_from', ''));
        $dateTo = trim((string) $request->get('date_to', ''));

        switch ($filterMode) {
            case 'week':
                $periodStart = date('Y-m-d', strtotime('monday this week'));
                $periodEnd = date('Y-m-d', strtotime('sunday this week'));
                $periodLabel = 'هذا الأسبوع';
                break;
            case 'month':
                $periodStart = date('Y-m-01');
                $periodEnd = date('Y-m-t');
                $periodLabel = 'هذا الشهر';
                break;
            case 'year':
                $periodStart = date('Y-01-01');
                $periodEnd = date('Y-12-31');
                $periodLabel = 'هذه السنة (' . date('Y') . ')';
                break;
            case '5years':
                $periodStart = date('Y-01-01', strtotime('-4 years'));
                $periodEnd = date('Y-12-31');
                $periodLabel = 'آخر 5 سنوات (' . date('Y', strtotime('-4 years')) . ' — ' . date('Y') . ')';
                break;
            case 'custom':
                $periodStart = $dateFrom ?: $today;
                $periodEnd = $dateTo ?: $today;
                $periodLabel = $periodStart . ' — ' . $periodEnd;
                break;
            default:
                $periodStart = $today;
                $periodEnd = $today;
                $periodLabel = 'اليوم';
                break;
        }

        $todayBookings = $db->select(
            "SELECT * FROM reservations WHERE facility_id = ? AND reservation_date = ? AND status NOT IN ('cancelled') ORDER BY start_time ASC",
            [(int) $id, $today]
        );

        $periodBookings = $db->select(
            "SELECT * FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled') ORDER BY reservation_date ASC, start_time ASC",
            [(int) $id, $periodStart, $periodEnd]
        );

        $periodRevenue = $db->selectOne(
            "SELECT COALESCE(SUM(total_amount), 0) AS total FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND payment_id IS NOT NULL AND status NOT IN ('cancelled')",
            [(int) $id, $periodStart, $periodEnd]
        );

        $todayRevenue = $db->selectOne(
            "SELECT COALESCE(SUM(total_amount), 0) AS total FROM reservations WHERE facility_id = ? AND reservation_date = ? AND payment_id IS NOT NULL AND status NOT IN ('cancelled')",
            [(int) $id, $today]
        );

        $weekStart = date('Y-m-d', strtotime('monday this week'));
        $weekRevenue = $db->selectOne(
            "SELECT COALESCE(SUM(total_amount), 0) AS total FROM reservations WHERE facility_id = ? AND reservation_date >= ? AND reservation_date <= ? AND payment_id IS NOT NULL AND status NOT IN ('cancelled')",
            [(int) $id, $weekStart, date('Y-m-d', strtotime('sunday this week'))]
        );

        $monthStart = date('Y-m-01');
        $monthRevenue = $db->selectOne(
            "SELECT COALESCE(SUM(total_amount), 0) AS total FROM reservations WHERE facility_id = ? AND reservation_date >= ? AND reservation_date <= ? AND payment_id IS NOT NULL AND status NOT IN ('cancelled')",
            [(int) $id, $monthStart, date('Y-m-t')]
        );

        $yearRevenue = $db->selectOne(
            "SELECT COALESCE(SUM(total_amount), 0) AS total FROM reservations WHERE facility_id = ? AND reservation_date >= ? AND reservation_date <= ? AND payment_id IS NOT NULL AND status NOT IN ('cancelled')",
            [(int) $id, date('Y-01-01'), date('Y-12-31')]
        );

        // Revenue by booker type
        $revenueByBookerType = $db->select(
            "SELECT booker_type, COUNT(*) AS booking_count, COALESCE(SUM(total_amount), 0) AS revenue
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')
             GROUP BY booker_type ORDER BY revenue DESC",
            [(int) $id, $periodStart, $periodEnd]
        );

        // Revenue by time tier
        $revenueByTimeTier = $db->select(
            "SELECT time_tier, COUNT(*) AS booking_count, COALESCE(SUM(total_amount), 0) AS revenue
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')
             GROUP BY time_tier ORDER BY revenue DESC",
            [(int) $id, $periodStart, $periodEnd]
        );

        // Peak hours analysis
        $peakHours = $db->select(
            "SELECT HOUR(start_time) AS hr, COUNT(*) AS cnt, COALESCE(SUM(total_amount), 0) AS revenue
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')
             GROUP BY hr ORDER BY cnt DESC LIMIT 10",
            [(int) $id, $periodStart, $periodEnd]
        );

        // Unique visitors
        $uniqueVisitors = $db->selectOne(
            "SELECT COUNT(DISTINCT CASE WHEN booker_id IS NOT NULL THEN booker_id ELSE booker_name END) AS cnt
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')",
            [(int) $id, $periodStart, $periodEnd]
        );

        // Monthly revenue trend (for chart)
        $monthlyTrend = $db->select(
            "SELECT DATE_FORMAT(reservation_date, '%Y-%m') AS month, COUNT(*) AS bookings, COALESCE(SUM(total_amount), 0) AS revenue
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')
             GROUP BY month ORDER BY month ASC",
            [(int) $id, $periodStart, $periodEnd]
        );

        // Occupancy rate calculation
        $totalSlots = $this->calculateTotalSlots((int) $id, $periodStart, $periodEnd);
        $occupiedSlots = count($periodBookings);
        $occupancyRate = $totalSlots > 0 ? round(($occupiedSlots / $totalSlots) * 100, 1) : 0;

        $upcomingBookings = $db->select(
            "SELECT * FROM reservations WHERE facility_id = ? AND reservation_date > ? AND status = 'confirmed' ORDER BY reservation_date ASC, start_time ASC LIMIT 10",
            [(int) $id, $today]
        );

        return $this->view('FacilityDashboards.Views.dashboard', [
            'facility'            => $facility,
            'todayBookings'       => $todayBookings,
            'periodBookings'      => $periodBookings,
            'todayRevenue'        => (float) ($todayRevenue['total'] ?? 0),
            'weekRevenue'         => (float) ($weekRevenue['total'] ?? 0),
            'monthRevenue'        => (float) ($monthRevenue['total'] ?? 0),
            'yearRevenue'         => (float) ($yearRevenue['total'] ?? 0),
            'periodRevenue'       => (float) ($periodRevenue['total'] ?? 0),
            'periodLabel'         => $periodLabel,
            'filterMode'          => $filterMode,
            'dateFrom'            => $dateFrom,
            'dateTo'              => $dateTo,
            'upcomingBookings'    => $upcomingBookings,
            'revenueByBookerType' => $revenueByBookerType,
            'revenueByTimeTier'   => $revenueByTimeTier,
            'peakHours'           => $peakHours,
            'uniqueVisitors'      => (int) ($uniqueVisitors['cnt'] ?? 0),
            'monthlyTrend'        => $monthlyTrend,
            'occupancyRate'       => $occupancyRate,
            'periodStart'         => $periodStart,
            'periodEnd'           => $periodEnd,
        ]);
    }

    public function exportPdf(Request $request, string $id): Response
    {
        $this->authorize('facility.dashboard');
        $db = App::getInstance()->db();

        $facility = $db->selectOne("SELECT * FROM facilities WHERE id = ? AND is_archived = 0", [(int) $id]);
        if (!$facility) {
            return $this->redirect('/facilities')->withError('المرفق غير موجود');
        }

        $filterMode = trim((string) $request->get('filter', 'month'));
        $dateFrom = trim((string) $request->get('date_from', date('Y-m-01')));
        $dateTo = trim((string) $request->get('date_to', date('Y-m-t')));

        switch ($filterMode) {
            case 'week':
                $periodStart = date('Y-m-d', strtotime('monday this week'));
                $periodEnd = date('Y-m-d', strtotime('sunday this week'));
                break;
            case 'month':
                $periodStart = date('Y-m-01');
                $periodEnd = date('Y-m-t');
                break;
            case 'year':
                $periodStart = date('Y-01-01');
                $periodEnd = date('Y-12-31');
                break;
            case '5years':
                $periodStart = date('Y-01-01', strtotime('-4 years'));
                $periodEnd = date('Y-12-31');
                break;
            default:
                $periodStart = $dateFrom;
                $periodEnd = $dateTo;
                break;
        }

        $summary = $db->selectOne(
            "SELECT COUNT(*) AS total_bookings, COALESCE(SUM(total_amount), 0) AS total_revenue,
                    COUNT(DISTINCT CASE WHEN booker_id IS NOT NULL THEN booker_id ELSE booker_name END) AS unique_visitors
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')",
            [(int) $id, $periodStart, $periodEnd]
        );

        $bookings = $db->select(
            "SELECT reservation_date, start_time, end_time, booker_type, booker_name, total_amount, status
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')
             ORDER BY reservation_date ASC, start_time ASC",
            [(int) $id, $periodStart, $periodEnd]
        );

        $byBookerType = $db->select(
            "SELECT booker_type, COUNT(*) AS cnt, COALESCE(SUM(total_amount), 0) AS revenue
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled')
             GROUP BY booker_type",
            [(int) $id, $periodStart, $periodEnd]
        );

        $html = $this->renderPdfHtml($facility, $periodStart, $periodEnd, $summary, $bookings, $byBookerType);

        $filename = 'facility_report_' . (int) $id . '_' . date('Ymd') . '.html';
        $filepath = sys_get_temp_dir() . '/' . $filename;
        file_put_contents($filepath, $html);

        return (new Response())
            ->setHeader('Content-Type', 'text/html; charset=utf-8')
            ->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
            ->setBody($html);
    }

    private function renderPdfHtml(array $facility, string $from, string $to, array $summary, array $bookings, array $byBookerType): string
    {
        $bookerLabels = ['member' => 'عضو', 'non_member' => 'غير عضو', 'player' => 'لاعب', 'guest' => 'ضيف', 'carnet_guest' => 'ضيف بدعوة'];

        $html = '<!DOCTYPE html><html dir="rtl" lang="ar"><head><meta charset="utf-8"><title>تقرير المرفق</title>';
        $html .= '<style>body{font-family:Arial,sans-serif;padding:30px;direction:rtl;} table{width:100%;border-collapse:collapse;margin:15px 0;} th,td{border:1px solid #ddd;padding:8px;text-align:right;font-size:13px;} th{background:#f5f5f5;} .header{text-align:center;margin-bottom:30px;} .stat{display:inline-block;width:30%;text-align:center;padding:15px;margin:5px;border:1px solid #ddd;border-radius:8px;}</style>';
        $html .= '</head><body>';
        $html .= '<div class="header"><h2>تقرير المرفق: ' . htmlspecialchars($facility['name_ar'] ?? '') . '</h2>';
        $html .= '<p>الفترة: ' . $from . ' إلى ' . $to . ' | تاريخ التقرير: ' . date('Y-m-d H:i') . '</p></div>';

        $html .= '<div style="text-align:center;margin:20px 0;">';
        $html .= '<div class="stat"><strong>' . number_format((float) ($summary['total_revenue'] ?? 0), 2) . '</strong><br>إجمالي الإيرادات (ج.م)</div>';
        $html .= '<div class="stat"><strong>' . (int) ($summary['total_bookings'] ?? 0) . '</strong><br>إجمالي الحجوزات</div>';
        $html .= '<div class="stat"><strong>' . (int) ($summary['unique_visitors'] ?? 0) . '</strong><br>زوار فريدون</div>';
        $html .= '</div>';

        if (!empty($byBookerType)) {
            $html .= '<h3>الإيرادات حسب نوع الحاجز</h3><table><tr><th>النوع</th><th>عدد الحجوزات</th><th>الإيرادات</th></tr>';
            foreach ($byBookerType as $row) {
                $html .= '<tr><td>' . ($bookerLabels[$row['booker_type']] ?? $row['booker_type']) . '</td><td>' . (int) $row['cnt'] . '</td><td>' . number_format((float) $row['revenue'], 2) . '</td></tr>';
            }
            $html .= '</table>';
        }

        if (!empty($bookings)) {
            $html .= '<h3>تفاصيل الحجوزات</h3><table><tr><th>التاريخ</th><th>الوقت</th><th>النوع</th><th>الاسم</th><th>المبلغ</th></tr>';
            foreach (array_slice($bookings, 0, 200) as $b) {
                $html .= '<tr><td>' . htmlspecialchars($b['reservation_date']) . '</td><td>' . htmlspecialchars(substr($b['start_time'], 0, 5) . '-' . substr($b['end_time'], 0, 5)) . '</td>';
                $html .= '<td>' . ($bookerLabels[$b['booker_type']] ?? $b['booker_type']) . '</td><td>' . htmlspecialchars($b['booker_name'] ?? '—') . '</td>';
                $html .= '<td>' . number_format((float) ($b['total_amount'] ?? 0), 2) . '</td></tr>';
            }
            $html .= '</table>';
        }

        $html .= '</body></html>';
        return $html;
    }

    private function calculateTotalSlots(int $facilityId, string $from, string $to): int
    {
        $db = App::getInstance()->db();
        $slots = $db->select("SELECT * FROM facility_time_slots WHERE facility_id = ?", [$facilityId]);
        if (empty($slots)) return 1;

        $days = max(1, (int) ((strtotime($to) - strtotime($from)) / 86400) + 1);
        return count($slots) * $days;
    }
}
