<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Request;
use App\Core\View;
use App\Repositories\RevenueRepository;
use App\Services\ChartDataService;
use DateTimeImmutable;

final class RevenueController
{
    public function index(): void
    {
        Auth::requireLogin();

        $user = Auth::user();
        $canAccessRevenue = (int)($user['dashboard_role_revenue'] ?? 0) === 1;
        if (!$canAccessRevenue) {
            http_response_code(403);
            View::render('errors/403', [
                'title' => current_lang() === 'ar' ? 'غير مصرح بالدخول' : 'Access not available',
                'activePage' => '',
            ]);
            return;
        }

        $currentYear = (int)date('Y');
        $mode = strtolower(trim((string)Request::get('mode', 'year')));
        if (!in_array($mode, ['year', 'range'], true)) {
            $mode = 'year';
        }

        $year = \safe_int(Request::get('year'), $currentYear);
        $compareYear = \safe_int(Request::get('compare_year'), $year - 1);
        $fromDate = $this->normalizeDate((string)Request::get('from_date', ''));
        $toDate = $this->normalizeDate((string)Request::get('to_date', ''));
        $filterError = '';

        if ($mode === 'range') {
            if ($fromDate === null) {
                $fromDate = sprintf('%04d-01-01', $year);
            }
            if ($toDate === null) {
                $toDate = sprintf('%04d-12-31', $year);
            }

            $from = new DateTimeImmutable($fromDate);
            $to = new DateTimeImmutable($toDate);
            if ($from > $to) {
                $filterError = current_lang() === 'ar'
                    ? 'يجب أن يكون تاريخ البداية قبل تاريخ النهاية.'
                    : 'From date must be on or before To date.';
                $toDate = $fromDate;
                $to = $from;
            }
            if ($from->format('Y') !== $to->format('Y')) {
                $filterError = current_lang() === 'ar'
                    ? 'يجب اختيار تاريخ البداية والنهاية داخل نفس السنة، كما في النظام السابق.'
                    : 'From date and To date must be within the same year, matching the legacy report contract.';
                $toDate = $from->format('Y') . '-12-31';
                $to = new DateTimeImmutable($toDate);
            }
            $year = (int)$from->format('Y');
            if ($compareYear === $year) {
                $compareYear = $year - 1;
            }
        } else {
            $fromDate = null;
            $toDate = null;
        }

        $hospitalCode = strtolower((string)Request::get('hospital', Auth::hospital()));
        if (!array_key_exists($hospitalCode, \config('hospitals', []))) {
            $hospitalCode = Auth::hospital();
        }

        $hospital = \config('hospitals.' . $hospitalCode);
        $repo = new RevenueRepository($hospitalCode);
        $chartService = new ChartDataService();

        $totalRows = $repo->monthlyRevenue($year, $compareYear, 'total', null, $fromDate, $toDate);
        $cashRows = $repo->monthlyRevenue($year, $compareYear, 'cash', null, $fromDate, $toDate);
        $insuranceRows = $repo->monthlyRevenue($year, $compareYear, 'insurance', null, $fromDate, $toDate);
        $mohRows = $repo->monthlyRevenue($year, $compareYear, 'moh', (string)$hospital['moh_customer_code'], $fromDate, $toDate);
        $profitLossRows = $repo->monthlyProfitLoss($year, $compareYear, (int)$hospital['profit_loss_company_id'], $fromDate, $toDate);

        $charts = [
            'total' => [
                'title' => 'Monthly Total Revenue',
                'rows' => $totalRows,
                'payload' => $chartService->comparePayload($totalRows, 'Monthly Total Revenue', $year, $compareYear),
            ],
            'cash' => [
                'title' => 'Monthly Total Cash Revenue',
                'rows' => $cashRows,
                'payload' => $chartService->comparePayload($cashRows, 'Monthly Total Cash Revenue', $year, $compareYear),
            ],
            'insurance' => [
                'title' => 'Monthly Total Insurance Revenue',
                'rows' => $insuranceRows,
                'payload' => $chartService->comparePayload($insuranceRows, 'Monthly Total Insurance Revenue', $year, $compareYear),
            ],
            'moh' => [
                'title' => 'Monthly Total MOH Revenue',
                'rows' => $mohRows,
                'payload' => $chartService->comparePayload($mohRows, 'Monthly Total MOH Revenue', $year, $compareYear),
            ],
            'profit_loss' => [
                'title' => 'Monthly Total Profit / Loss',
                'rows' => $profitLossRows,
                'payload' => $chartService->comparePayload($profitLossRows, 'Monthly Total Profit / Loss', $year, $compareYear),
            ],
        ];

        $cards = [];
        foreach ($charts as $key => $chart) {
            $currentTotal = $chartService->total($chart['rows'], 'current_value');
            $compareTotal = $chartService->total($chart['rows'], 'compare_value');
            $cards[$key] = [
                'title' => $chart['title'],
                'current_total' => $currentTotal,
                'compare_total' => $compareTotal,
                'percent' => $chartService->percentChange($currentTotal, $compareTotal),
            ];
        }

        $compareFromDate = $fromDate !== null ? RevenueRepository::shiftDateToYear($fromDate, $compareYear) : null;
        $compareToDate = $toDate !== null ? RevenueRepository::shiftDateToYear($toDate, $compareYear) : null;

        View::render('revenue/index', [
            'title' => 'Revenue Dashboard',
            'activePage' => 'revenue',
            'mode' => $mode,
            'year' => $year,
            'compareYear' => $compareYear,
            'fromDate' => $fromDate,
            'toDate' => $toDate,
            'compareFromDate' => $compareFromDate,
            'compareToDate' => $compareToDate,
            'filterError' => $filterError,
            'hospitalCode' => $hospitalCode,
            'hospital' => $hospital,
            'hospitals' => \config('hospitals'),
            'charts' => $charts,
            'cards' => $cards,
        ]);
    }

    private function normalizeDate(string $value): ?string
    {
        $value = trim($value);
        if ($value === '') {
            return null;
        }
        $date = DateTimeImmutable::createFromFormat('!Y-m-d', $value);
        $errors = DateTimeImmutable::getLastErrors();
        if ($date === false) {
            return null;
        }
        if (is_array($errors) && ((int)($errors['warning_count'] ?? 0) > 0 || (int)($errors['error_count'] ?? 0) > 0)) {
            return null;
        }
        return $date->format('Y-m-d');
    }
}
