<?php
declare(strict_types=1);

namespace App\Modules\PlaygroundAdmin\Services;

use App\Core\App;

final class ClubDashboardService
{
    private \App\Core\Database $db;

    public function __construct()
    {
        $this->db = App::getInstance()->db();
    }

    public function getClubWideData(string $dateFrom, string $dateTo): array
    {
        $totalRevenue = $this->db->selectOne(
            "SELECT COALESCE(SUM(total_amount), 0) as total FROM reservations
             WHERE reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled', 'no_show')",
            [$dateFrom, $dateTo]
        );

        $freeTimeRevenue = $this->db->selectOne(
            "SELECT COALESCE(SUM(amount_paid), 0) as total, COUNT(*) as entries FROM free_time_entries
             WHERE entry_date BETWEEN ? AND ? AND status = 'active'",
            [$dateFrom, $dateTo]
        );

        $bookingsByFacility = $this->db->select(
            "SELECT f.name_ar as facility_name, f.facility_type, COUNT(r.id) as bookings,
                    COALESCE(SUM(r.total_amount), 0) as revenue
             FROM reservations r
             INNER JOIN facilities f ON f.id = r.facility_id
             WHERE r.reservation_date BETWEEN ? AND ? AND r.status NOT IN ('cancelled', 'no_show')
             GROUP BY f.id, f.name_ar, f.facility_type
             ORDER BY revenue DESC",
            [$dateFrom, $dateTo]
        );

        $uniquePlayers = $this->db->selectOne(
            "SELECT COUNT(DISTINCT booker_id) as cnt FROM reservations
             WHERE reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled', 'no_show')",
            [$dateFrom, $dateTo]
        );

        $activeCoaches = $this->db->selectOne(
            "SELECT COUNT(DISTINCT coach_id) as cnt FROM training_sessions
             WHERE session_date BETWEEN ? AND ? AND status != 'cancelled'",
            [$dateFrom, $dateTo]
        );

        $attendanceRate = $this->db->selectOne(
            "SELECT ROUND(AVG(CASE WHEN status = 'present' THEN 100.0 ELSE 0.0 END), 1) as rate
             FROM facility_attendance WHERE attendance_date BETWEEN ? AND ?",
            [$dateFrom, $dateTo]
        );

        $playgroundStats = $this->db->select(
            "SELECT pc.playground_name_ar, pc.playground_type,
                    COUNT(DISTINCT r.id) as bookings,
                    COALESCE(SUM(r.total_amount), 0) as revenue
             FROM playground_configurations pc
             INNER JOIN facilities f ON f.id = pc.facility_id
             LEFT JOIN reservations r ON r.facility_id = f.id
                  AND r.reservation_date BETWEEN ? AND ?
                  AND r.status NOT IN ('cancelled', 'no_show')
             WHERE pc.is_active = 1
             GROUP BY pc.id, pc.playground_name_ar, pc.playground_type
             ORDER BY revenue DESC",
            [$dateFrom, $dateTo]
        );

        $monthlyTrend = $this->db->select(
            "SELECT DATE_FORMAT(reservation_date, '%Y-%m') as month,
                    COUNT(*) as bookings, COALESCE(SUM(total_amount), 0) as revenue
             FROM reservations
             WHERE reservation_date BETWEEN ? AND ? AND status NOT IN ('cancelled', 'no_show')
             GROUP BY month ORDER BY month",
            [$dateFrom, $dateTo]
        );

        return [
            'total_revenue' => (float) ($totalRevenue['total'] ?? 0) + (float) ($freeTimeRevenue['total'] ?? 0),
            'booking_revenue' => (float) ($totalRevenue['total'] ?? 0),
            'free_time_revenue' => (float) ($freeTimeRevenue['total'] ?? 0),
            'free_time_entries' => (int) ($freeTimeRevenue['entries'] ?? 0),
            'unique_players' => (int) ($uniquePlayers['cnt'] ?? 0),
            'active_coaches' => (int) ($activeCoaches['cnt'] ?? 0),
            'avg_attendance_rate' => (float) ($attendanceRate['rate'] ?? 0),
            'bookings_by_facility' => $bookingsByFacility,
            'playground_stats' => $playgroundStats,
            'monthly_trend' => $monthlyTrend,
            'period' => ['from' => $dateFrom, 'to' => $dateTo],
        ];
    }

    public function getPlaygroundData(int $playgroundId, string $dateFrom, string $dateTo): array
    {
        $playground = $this->db->selectOne(
            "SELECT pc.*, f.name_ar as facility_name FROM playground_configurations pc
             LEFT JOIN facilities f ON f.id = pc.facility_id WHERE pc.id = ?",
            [$playgroundId]
        );

        if (!$playground) return [];

        $facilityId = (int) $playground['facility_id'];

        $revenue = $this->db->selectOne(
            "SELECT COALESCE(SUM(total_amount), 0) as total, COUNT(*) as bookings
             FROM reservations WHERE facility_id = ? AND reservation_date BETWEEN ? AND ?
             AND status NOT IN ('cancelled', 'no_show')",
            [$facilityId, $dateFrom, $dateTo]
        );

        $uniqueUsers = $this->db->selectOne(
            "SELECT COUNT(DISTINCT booker_id) as cnt FROM reservations
             WHERE facility_id = ? AND reservation_date BETWEEN ? AND ?
             AND status NOT IN ('cancelled', 'no_show')",
            [$facilityId, $dateFrom, $dateTo]
        );

        $attendance = [];
        if ($playground['grid_id']) {
            $attendance = $this->db->selectOne(
                "SELECT COUNT(*) as total,
                        SUM(CASE WHEN status = 'present' THEN 1 ELSE 0 END) as present_count,
                        ROUND(AVG(CASE WHEN status = 'present' THEN 100.0 ELSE 0.0 END), 1) as rate
                 FROM facility_attendance WHERE grid_id = ? AND attendance_date BETWEEN ? AND ?",
                [(int) $playground['grid_id'], $dateFrom, $dateTo]
            );
        }

        return [
            'playground' => $playground,
            'total_revenue' => (float) ($revenue['total'] ?? 0),
            'total_bookings' => (int) ($revenue['bookings'] ?? 0),
            'unique_users' => (int) ($uniqueUsers['cnt'] ?? 0),
            'attendance' => $attendance ?: ['total' => 0, 'present_count' => 0, 'rate' => 0],
            'period' => ['from' => $dateFrom, 'to' => $dateTo],
        ];
    }

    public function getDateRange(string $filter, ?string $from = null, ?string $to = null): array
    {
        $today = date('Y-m-d');
        return match ($filter) {
            'daily' => ['from' => $today, 'to' => $today],
            'weekly' => ['from' => date('Y-m-d', strtotime('monday this week')), 'to' => date('Y-m-d', strtotime('sunday this week'))],
            'monthly' => ['from' => date('Y-m-01'), 'to' => date('Y-m-t')],
            'yearly' => ['from' => date('Y-01-01'), 'to' => date('Y-12-31')],
            '3years' => ['from' => date('Y-m-d', strtotime('-3 years')), 'to' => $today],
            '5years' => ['from' => date('Y-m-d', strtotime('-5 years')), 'to' => $today],
            'custom' => ['from' => $from ?? $today, 'to' => $to ?? $today],
            default => ['from' => date('Y-m-01'), 'to' => date('Y-m-t')],
        };
    }
}
