<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\AccessControl;
use App\Core\Auth;
use App\Core\Request;
use App\Core\View;
use App\Repositories\InpatientDailyRevenueRepository;
use App\Repositories\InpatientDailyRevenueRuleSettingsRepository;
use App\Services\InpatientDailyRevenueService;
use App\Services\XlsxExportService;
use App\Services\PowerBiDailyRevenueExportService;
use App\Services\PowerPointDailyRevenueExportService;
use Throwable;

final class InpatientDailyRevenueController
{
    public function index(): void
    {
        Auth::requireLogin();
        if (!$this->canAccess()) {
            $this->forbidden();
            return;
        }

        $hospitalCode = Auth::hospital();
        $loadResult = $this->loadReport($hospitalCode);
        $report = $loadResult['report'];
        $errorMessage = $loadResult['errorMessage'];

        $powerBiReportStatus = (new PowerBiDailyRevenueExportService())->reportStatus();

        View::render('inpatient_daily_revenue/index', [
            'title' => current_lang() === 'ar' ? 'الإيراد اليومي للمرضى المنومين' : 'Daily Inpatient Revenue',
            'activePage' => 'inpatient-daily-revenue',
            'hospitalCode' => $hospitalCode,
            'hospital' => \config('hospitals.' . $hospitalCode, []),
            'report' => $report,
            'errorMessage' => $errorMessage,
            'powerBiReportStatus' => $powerBiReportStatus,
        ]);
    }

    public function export(): void
    {
        Auth::requireLogin();
        if (!$this->canAccess()) {
            http_response_code(403);
            return;
        }

        $hospitalCode = Auth::hospital();
        $loadResult = $this->loadReport($hospitalCode);
        $report = $loadResult['report'];
        $errorMessage = $loadResult['errorMessage'];
        if ($errorMessage !== '') {
            http_response_code(503);
            echo $errorMessage;
            return;
        }

        $hospital = \config('hospitals.' . $hospitalCode, []);
        $report['hospital_code'] = strtoupper($hospitalCode);
        $report['hospital_name'] = is_array($hospital) ? (string)($hospital['name'] ?? '') : '';
        $filename = strtoupper($hospitalCode) . '_Daily_Revenue_' . date('Y-m-d') . '.xlsx';

        (new XlsxExportService())->streamFinalWorkbook($report, $filename);
    }


    public function exportPowerBi(): void
    {
        Auth::requireLogin();
        if (!$this->canAccess()) {
            http_response_code(403);
            return;
        }

        $powerBiExport = new PowerBiDailyRevenueExportService();
        $powerBiStatus = $powerBiExport->reportStatus();
        if (($powerBiStatus['available'] ?? false) !== true) {
            http_response_code(409);
            error_log('[PowerBI Export] unavailable state=' . (string)($powerBiStatus['state'] ?? 'UNKNOWN')
                . ' reason=' . (string)($powerBiStatus['reason'] ?? 'UNKNOWN'));
            echo current_lang() === 'ar'
                ? 'تقرير Power BI غير متاح للتصدير حاليًا.'
                : 'The Power BI report is not currently available for export.';
            return;
        }

        $hospitalCode = Auth::hospital();
        $loadResult = $this->loadReport($hospitalCode);
        $report = $loadResult['report'];
        $errorMessage = $loadResult['errorMessage'];
        if ($errorMessage !== '') {
            http_response_code(503);
            echo $errorMessage;
            return;
        }

        $hospital = \config('hospitals.' . $hospitalCode, []);
        $report['hospital_code'] = strtoupper($hospitalCode);
        $report['hospital_name'] = is_array($hospital) ? (string)($hospital['name'] ?? '') : '';
        $filename = strtoupper($hospitalCode) . '_Daily_Revenue_PowerBI_Package_' . date('Y-m-d') . '.zip';

        $powerBiExport->stream($report, $filename);
    }

    public function exportPowerPoint(): void
    {
        Auth::requireLogin();
        if (!$this->canAccess()) {
            http_response_code(403);
            return;
        }

        $hospitalCode = Auth::hospital();
        $loadResult = $this->loadReport($hospitalCode);
        $report = $loadResult['report'];
        $errorMessage = $loadResult['errorMessage'];
        if ($errorMessage !== '') {
            http_response_code(503);
            echo $errorMessage;
            return;
        }

        $hospital = \config('hospitals.' . $hospitalCode, []);
        $report['hospital_code'] = strtoupper($hospitalCode);
        $report['hospital_name'] = is_array($hospital) ? (string)($hospital['name'] ?? '') : '';
        $filename = strtoupper($hospitalCode) . '_Daily_Revenue_Brief_' . date('Y-m-d') . '.pptx';

        (new PowerPointDailyRevenueExportService())->stream($report, $filename);
    }

    private function canAccess(): bool
    {
        return AccessControl::allows('daily_inpatient_revenue.view');
    }

    /**
     * @return array{report: array<string,mixed>, errorMessage: string}
     */
    private function loadReport(string $hospitalCode): array
    {
        try {
            $rulesRepository = new InpatientDailyRevenueRuleSettingsRepository($hospitalCode);
            $rules = $rulesRepository->load();
            $rows = (new InpatientDailyRevenueRepository($hospitalCode))->currentInpatientsWithRevenue();
            $report = (new InpatientDailyRevenueService($hospitalCode, $rules))->build($rows);
            $report['business_rules'] = $rules;
            return [
                'report' => $report,
                'errorMessage' => '',
            ];
        } catch (Throwable $e) {
            $errorMessage = current_lang() === 'ar'
                ? 'تعذر تحميل الإيراد اليومي في الوقت الحالي. يرجى المحاولة مرة أخرى بعد قليل.'
                : 'Daily inpatient revenue is temporarily unavailable. Please try again shortly.';
            error_log('[InpatientDailyRevenue] ' . $e->getMessage());

            try {
                $fallbackRules = (new InpatientDailyRevenueRuleSettingsRepository($hospitalCode))->defaults();
            } catch (Throwable $ignored) {
                $fallbackRules = (array)\config('inpatient_daily_revenue_rules.branches.' . $hospitalCode, []);
            }
            $report = (new InpatientDailyRevenueService($hospitalCode, $fallbackRules))->build([]);
            $report['business_rules'] = $fallbackRules;
            return [
                'report' => $report,
                'errorMessage' => $errorMessage,
            ];
        }
    }

    private function forbidden(): void
    {
        http_response_code(403);
        View::render('errors/403', [
            'title' => current_lang() === 'ar' ? 'غير مصرح بالدخول' : 'Access not available',
            'activePage' => '',
        ]);
    }
}
