<?php
declare(strict_types=1);

namespace App\Modules\SportsDashboard\Services;

use App\Core\App;

final class DashboardMetricsService
{
    public static function getDateRange(string $period, ?string $from = null, ?string $to = null): array
    {
        $end = $to ?? date('Y-m-d');
        $start = match ($period) {
            'day'    => $end,
            'week'   => date('Y-m-d', strtotime('-7 days', strtotime($end))),
            'month'  => date('Y-m-d', strtotime('-1 month', strtotime($end))),
            'year'   => date('Y-m-d', strtotime('-1 year', strtotime($end))),
            '3year'  => date('Y-m-d', strtotime('-3 years', strtotime($end))),
            '5year'  => date('Y-m-d', strtotime('-5 years', strtotime($end))),
            'custom' => $from ?? date('Y-m-d', strtotime('-1 month', strtotime($end))),
            default  => date('Y-m-d', strtotime('-1 month', strtotime($end))),
        };
        return ['start' => $start, 'end' => $end];
    }

    public static function getRevenue(string $start, string $end, ?int $facilityId = null, ?int $disciplineId = null): array
    {
        $db = App::getInstance()->db();
        $where = "p.payment_date BETWEEN ? AND ? AND p.payment_type IN ('activity_booking','pool_booking','sports_subscription') AND p.is_voided = 0";
        $params = [$start, $end];

        if ($facilityId) {
            $where .= " AND p.related_entity_type = 'facility' AND p.related_entity_id = ?";
            $params[] = $facilityId;
        }

        if ($disciplineId) {
            $where .= " AND p.related_entity_type = 'discipline' AND p.related_entity_id = ?";
            $params[] = $disciplineId;
        }

        $total = $db->selectOne("SELECT COALESCE(SUM(p.amount), 0) as total FROM payments p WHERE {$where}", $params);
        return ['total' => $total['total'] ?? '0.00'];
    }

    public static function getPlayerDemographics(?int $disciplineId = null): array
    {
        $db = App::getInstance()->db();
        $where = "is_archived = 0";
        $params = [];

        if ($disciplineId) {
            $where .= " AND id IN (SELECT player_id FROM activity_subscriptions WHERE discipline_id = ? AND status = 'active')";
            $params[] = $disciplineId;
        }

        $members = $db->selectOne("SELECT COUNT(*) as cnt FROM players WHERE {$where} AND player_type = 'member'", $params);
        $nonMembers = $db->selectOne("SELECT COUNT(*) as cnt FROM players WHERE {$where} AND player_type = 'non_member'", $params);

        return [
            'members'     => (int) ($members['cnt'] ?? 0),
            'non_members' => (int) ($nonMembers['cnt'] ?? 0),
            'total'       => (int) ($members['cnt'] ?? 0) + (int) ($nonMembers['cnt'] ?? 0),
        ];
    }

    public static function getDisciplineBreakdown(string $start, string $end): array
    {
        $db = App::getInstance()->db();

        return $db->select("
            SELECT d.id, d.name_ar, d.name_en,
                   COALESCE(SUM(p.amount), 0) AS revenue,
                   COUNT(DISTINCT asub.player_id) AS player_count
            FROM disciplines d
            LEFT JOIN activity_subscriptions asub ON asub.discipline_id = d.id AND asub.status = 'active'
            LEFT JOIN payments p ON p.related_entity_type = 'discipline' AND p.related_entity_id = d.id
                AND p.payment_date BETWEEN ? AND ? AND p.is_voided = 0
            WHERE d.is_archived = 0
            GROUP BY d.id, d.name_ar, d.name_en
            ORDER BY revenue DESC
        ", [$start, $end]);
    }

    public static function getFacilityUtilization(string $start, string $end, ?int $facilityId = null): array
    {
        $db = App::getInstance()->db();
        $params = [$start, $end];
        $facilityWhere = '';

        if ($facilityId) {
            $facilityWhere = ' AND f.id = ?';
            $params[] = $facilityId;
        }

        $facilities = $db->select("
            SELECT f.id, f.name_ar,
                   (SELECT COUNT(*) FROM reservations r WHERE r.facility_id = f.id AND r.reservation_date BETWEEN ? AND ? AND r.status NOT IN ('cancelled')) AS booked_slots
            FROM facilities f
            WHERE f.is_archived = 0 {$facilityWhere}
        ", $params);

        foreach ($facilities as &$fac) {
            $slots = $db->select("SELECT COUNT(*) as cnt FROM facility_time_slots WHERE facility_id = ?", [(int) $fac['id']]);
            $slotsPerDay = (int) ($slots[0]['cnt'] ?? 1);
            $days = max(1, (int) ((strtotime($end) - strtotime($start)) / 86400) + 1);
            $totalSlots = $slotsPerDay * $days;
            $fac['total_slots'] = $totalSlots;
            $fac['utilization'] = $totalSlots > 0 ? round(((int) $fac['booked_slots'] / $totalSlots) * 100, 1) : 0;
        }

        return $facilities;
    }

    public static function getPreviousPeriodComparison(string $currentStart, string $currentEnd, string $metric, ?int $facilityId = null, ?int $disciplineId = null): array
    {
        $duration = strtotime($currentEnd) - strtotime($currentStart);
        $prevEnd = date('Y-m-d', strtotime($currentStart) - 86400);
        $prevStart = date('Y-m-d', strtotime($prevEnd) - $duration);

        $current = self::getRevenue($currentStart, $currentEnd, $facilityId, $disciplineId);
        $previous = self::getRevenue($prevStart, $prevEnd, $facilityId, $disciplineId);

        $currentVal = (float) $current['total'];
        $previousVal = (float) $previous['total'];
        $change = $previousVal > 0 ? round((($currentVal - $previousVal) / $previousVal) * 100, 1) : 0;

        return [
            'current'    => $currentVal,
            'previous'   => $previousVal,
            'change_pct' => $change,
            'direction'  => $change >= 0 ? 'up' : 'down',
        ];
    }

    public static function getCoachesForDiscipline(int $disciplineId, string $start, string $end): array
    {
        $db = App::getInstance()->db();

        return $db->select("
            SELECT DISTINCT c.id, c.name_ar, c.name_en,
                   (SELECT COUNT(*) FROM facility_zone_schedules fzs2 WHERE fzs2.coach_id = c.id AND fzs2.schedule_date BETWEEN ? AND ?) AS session_count
            FROM coaches c
            INNER JOIN facility_zone_schedules fzs ON fzs.coach_id = c.id
            WHERE fzs.discipline_id = ? AND fzs.schedule_date BETWEEN ? AND ?
            ORDER BY session_count DESC
        ", [$start, $end, $disciplineId, $start, $end]);
    }

    public static function getPopularTimeSlots(int $facilityId, string $start, string $end): array
    {
        $db = App::getInstance()->db();

        return $db->select("
            SELECT HOUR(start_time) AS hour_slot, 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 hour_slot
            ORDER BY booking_count DESC
            LIMIT 10
        ", [$facilityId, $start, $end]);
    }
}
