<?php
declare(strict_types=1);

namespace App\Modules\Reports\Services;

use App\Core\App;

final class AcademyRevenueReportService
{
    /**
     * Generate academy revenue report: actual vs minimum guarantee, surplus/shortfall, trends.
     *
     * @param string   $periodFrom Start date (YYYY-MM-DD)
     * @param string   $periodTo   End date (YYYY-MM-DD)
     * @param int|null $academyId  Filter by specific academy (null = all)
     * @return array Report data
     */
    public static function generate(string $periodFrom, string $periodTo, ?int $academyId = null): array
    {
        $db = App::getInstance()->db();

        // Get academies with their contract details
        $params = [$periodFrom, $periodTo];
        $academyFilter = '';
        if ($academyId !== null) {
            $academyFilter = ' AND a.id = ?';
            $params[] = $academyId;
        }

        $academies = $db->select(
            "SELECT a.id, a.name_ar, a.code,
                    ac.minimum_guarantee, ac.revenue_share_percent, ac.start_date, ac.end_date
             FROM academies a
             LEFT JOIN academy_contracts ac ON ac.academy_id = a.id AND ac.status = 'active'
             WHERE a.is_archived = 0{$academyFilter}
             ORDER BY a.name_ar ASC",
            $academyId !== null ? [$academyId] : []
        );

        $results = [];
        $totals = [
            'total_revenue'      => 0,
            'total_guarantee'    => 0,
            'total_surplus'      => 0,
            'total_shortfall'    => 0,
            'academy_count'      => 0,
        ];

        foreach ($academies as $academy) {
            $aId = (int) $academy['id'];

            // Calculate actual revenue from payments
            $revenue = $db->selectOne(
                "SELECT COALESCE(SUM(p.amount), 0) AS total_revenue
                 FROM payments p
                 WHERE p.payable_type = 'academy'
                   AND p.payable_id = ?
                   AND p.payment_date BETWEEN ? AND ?
                   AND p.status = 'completed'",
                [$aId, $periodFrom, $periodTo]
            );

            $actualRevenue = (float) ($revenue['total_revenue'] ?? 0);
            $minimumGuarantee = (float) ($academy['minimum_guarantee'] ?? 0);

            // Calculate months in period for prorating guarantee
            $monthsInPeriod = self::monthsBetween($periodFrom, $periodTo);
            $proratedGuarantee = $minimumGuarantee * $monthsInPeriod;

            $surplus = max(0, $actualRevenue - $proratedGuarantee);
            $shortfall = max(0, $proratedGuarantee - $actualRevenue);

            // Monthly trend
            $monthlyRevenue = $db->select(
                "SELECT DATE_FORMAT(p.payment_date, '%Y-%m') AS month,
                        COALESCE(SUM(p.amount), 0) AS revenue
                 FROM payments p
                 WHERE p.payable_type = 'academy'
                   AND p.payable_id = ?
                   AND p.payment_date BETWEEN ? AND ?
                   AND p.status = 'completed'
                 GROUP BY DATE_FORMAT(p.payment_date, '%Y-%m')
                 ORDER BY month ASC",
                [$aId, $periodFrom, $periodTo]
            );

            $results[] = [
                'academy_id'        => $aId,
                'academy_name'      => $academy['name_ar'],
                'academy_code'      => $academy['code'],
                'actual_revenue'    => $actualRevenue,
                'minimum_guarantee' => $proratedGuarantee,
                'surplus'           => $surplus,
                'shortfall'         => $shortfall,
                'revenue_share_percent' => (float) ($academy['revenue_share_percent'] ?? 0),
                'monthly_trend'     => $monthlyRevenue,
                'contract_start'    => $academy['start_date'],
                'contract_end'      => $academy['end_date'],
            ];

            $totals['total_revenue'] += $actualRevenue;
            $totals['total_guarantee'] += $proratedGuarantee;
            $totals['total_surplus'] += $surplus;
            $totals['total_shortfall'] += $shortfall;
            $totals['academy_count']++;
        }

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

    /**
     * Calculate approximate months between two dates.
     */
    private static function monthsBetween(string $from, string $to): float
    {
        $d1 = new \DateTime($from);
        $d2 = new \DateTime($to);
        $diff = $d1->diff($d2);
        return $diff->m + ($diff->y * 12) + ($diff->d / 30);
    }
}
