<?php
declare(strict_types=1);

namespace App\Modules\Reports\Services;

use App\Core\App;

final class CoachUtilizationReportService
{
    /**
     * Generate coach utilization report: sessions, players, hours, revenue.
     *
     * @param string   $periodFrom Start date (YYYY-MM-DD)
     * @param string   $periodTo   End date (YYYY-MM-DD)
     * @param int|null $coachId    Filter by specific coach (null = all)
     * @return array Report data
     */
    public static function generate(string $periodFrom, string $periodTo, ?int $coachId = null): array
    {
        $db = App::getInstance()->db();

        $params = [$periodFrom, $periodTo];
        $coachFilter = '';
        if ($coachId !== null) {
            $coachFilter = ' AND c.id = ?';
            $params[] = $coachId;
        }

        $coaches = $db->select(
            "SELECT c.id, c.full_name_ar, c.code, c.payment_model, c.session_rate, c.hourly_rate, c.monthly_rate
             FROM coaches c
             WHERE c.is_active = 1 AND c.is_archived = 0{$coachFilter}
             ORDER BY c.full_name_ar ASC",
            $coachId !== null ? [$coachId] : []
        );

        $results = [];
        $totals = [
            'total_sessions'       => 0,
            'total_players_served' => 0,
            'total_hours'          => 0,
            'total_revenue'        => 0,
            'coach_count'          => 0,
        ];

        foreach ($coaches as $coach) {
            $cId = (int) $coach['id'];

            // Sessions conducted
            $sessionData = $db->selectOne(
                "SELECT COUNT(*) AS session_count,
                        COALESCE(SUM(TIMESTAMPDIFF(MINUTE, ts.start_time, ts.end_time)), 0) AS total_minutes
                 FROM training_sessions ts
                 WHERE ts.coach_id = ?
                   AND ts.session_date BETWEEN ? AND ?
                   AND ts.status = 'completed'",
                [$cId, $periodFrom, $periodTo]
            );

            $sessionsConducted = (int) ($sessionData['session_count'] ?? 0);
            $totalMinutes = (int) ($sessionData['total_minutes'] ?? 0);
            $totalHours = round($totalMinutes / 60, 1);

            // Players served
            $playerData = $db->selectOne(
                "SELECT COALESCE(SUM(sa_count.cnt), 0) AS total_players,
                        COUNT(DISTINCT sa_count.player_id) AS unique_players
                 FROM (
                     SELECT sa.player_id, COUNT(*) AS cnt
                     FROM session_attendance sa
                     INNER JOIN training_sessions ts ON ts.id = sa.session_id
                     WHERE ts.coach_id = ?
                       AND ts.session_date BETWEEN ? AND ?
                       AND ts.status = 'completed'
                       AND sa.status = 'present'
                     GROUP BY sa.player_id
                 ) sa_count",
                [$cId, $periodFrom, $periodTo]
            );

            $totalPlayersServed = (int) ($playerData['total_players'] ?? 0);
            $uniquePlayers = (int) ($playerData['unique_players'] ?? 0);

            // Revenue attributed (from coach_payments if exists)
            $revenueData = $db->selectOne(
                "SELECT COALESCE(SUM(cp.net_amount), 0) AS total_paid
                 FROM coach_payments cp
                 WHERE cp.coach_id = ?
                   AND cp.payment_period >= ?
                   AND cp.payment_period <= ?
                   AND cp.status IN ('approved', 'paid')",
                [$cId, substr($periodFrom, 0, 7), substr($periodTo, 0, 7)]
            );

            $revenueAttributed = (float) ($revenueData['total_paid'] ?? 0);

            // Utilization rate (sessions per available day)
            $workingDays = self::workingDaysBetween($periodFrom, $periodTo);
            $utilizationRate = $workingDays > 0 ? round(($sessionsConducted / $workingDays) * 100, 1) : 0;

            $results[] = [
                'coach_id'             => $cId,
                'coach_name'           => $coach['full_name_ar'],
                'coach_code'           => $coach['code'],
                'payment_model'        => $coach['payment_model'],
                'sessions_conducted'   => $sessionsConducted,
                'total_players_served' => $totalPlayersServed,
                'unique_players'       => $uniquePlayers,
                'total_hours'          => $totalHours,
                'revenue_attributed'   => $revenueAttributed,
                'utilization_rate'     => $utilizationRate,
            ];

            $totals['total_sessions'] += $sessionsConducted;
            $totals['total_players_served'] += $totalPlayersServed;
            $totals['total_hours'] += $totalHours;
            $totals['total_revenue'] += $revenueAttributed;
            $totals['coach_count']++;
        }

        return [
            'period_from' => $periodFrom,
            'period_to'   => $periodTo,
            'coaches'     => $results,
            'totals'      => $totals,
        ];
    }

    /**
     * Approximate working days between two dates (excluding Fridays).
     */
    private static function workingDaysBetween(string $from, string $to): int
    {
        $start = new \DateTime($from);
        $end = new \DateTime($to);
        $days = 0;

        while ($start <= $end) {
            // Friday = 5 in PHP (0=Sunday)
            if ((int) $start->format('w') !== 5) {
                $days++;
            }
            $start->modify('+1 day');
        }

        return $days;
    }
}
