<?php

declare(strict_types=1);

namespace App\Services;

use App\Repositories\LegacySpecialtyFinanceRepository;
use App\Repositories\SpecialtyFinanceRepository;

final class SpecialtyFinanceParityService
{
    /** @var string */
    private $hospitalCode;

    /** @var LegacySpecialtyFinanceRepository */
    private $legacy;

    /** @var SpecialtyFinanceRepository */
    private $current;

    public function __construct(string $hospitalCode)
    {
        $this->hospitalCode = strtolower($hospitalCode);
        $this->legacy = new LegacySpecialtyFinanceRepository($this->hospitalCode);
        $this->current = new SpecialtyFinanceRepository($this->hospitalCode);
    }

    /** @return array<string, mixed> */
    public function run(int $year, int $compareYear): array
    {
        $periods = [
            'current_year' => $year,
            'compare_year' => $compareYear,
        ];

        $modes = [];
        $all = [];
        foreach ($periods as $mode => $periodYear) {
            $functions = [
                $this->compareScalar(
                    'moh_revn',
                    'get_moh_revn',
                    $periodYear,
                    $this->legacy->mohRevenue($periodYear),
                    $this->current->annualMetricTotal($periodYear, 'MOH')
                ),
                $this->compareScalar(
                    'drug_rev',
                    'get_drug_rev',
                    $periodYear,
                    $this->legacy->drugRevenue($periodYear),
                    $this->current->annualMetricTotal($periodYear, 'DRUG_REV')
                ),
                $this->compareScalar(
                    'net_rev',
                    'get_net_rev',
                    $periodYear,
                    $this->legacy->netRevenue($periodYear),
                    $this->current->annualMetricTotal($periodYear, 'NET_REV_AFTER_DRUG_MOH')
                ),
            ];
            $modes[$mode] = ['year' => $periodYear, 'functions' => $functions];
            foreach ($functions as $row) {
                $all[] = $row;
            }
        }

        $failures = count(array_filter($all, static function (array $row): bool {
            return ($row['status'] ?? 'FAIL') !== 'PASS';
        }));
        $maxDifference = 0.0;
        foreach ($all as $row) {
            $maxDifference = max($maxDifference, (float)($row['max_difference'] ?? 0));
        }

        return [
            'schema_version' => '1.0',
            'phase' => '10.15',
            'hospital' => strtoupper($this->hospitalCode),
            'year' => $year,
            'compare_year' => $compareYear,
            'write_operations' => 'NONE',
            'source_contract' => [
                'moh_revn' => 'Dispatcher confirmed as get_moh_revn; reconstructed annual selected-branch contract on KPI_DOCTOR_PERF_DETAIL_JOB.MOH.',
                'drug_rev' => 'Dispatcher confirmed as get_drug_rev; reconstructed annual selected-branch contract on KPI_DOCTOR_PERF_DETAIL_JOB.DRUG_REV.',
                'net_rev' => 'Dispatcher confirmed as get_net_rev; reconstructed annual selected-branch contract on KPI_DOCTOR_PERF_DETAIL_JOB.NET_REV_AFTER_DRUG_MOH.',
                'aggregation_note' => 'Doctor-level values are deduplicated per doctor before final aggregation, preserving the established doctor KPI contract validated in Phase 10.13.',
                'source_evidence_boundary' => 'The supplied legacy archive does not contain the full historical bodies of get_moh_revn, get_drug_rev or get_net_rev. Phase 10.15 proves zero-difference parity between independent reconstructed legacy/current SQL paths on the established KPI source; it does not claim source-code identity with missing historical bodies.',
                'blocked_out_of_scope' => 'special_prof and special_net_rev remain BLOCKED_SOURCE_MISSING until their historical function bodies or approved replacement rules are supplied.',
            ],
            'modes' => $modes,
            'checks' => $all,
            'functions_checked' => count($all),
            'max_difference' => $maxDifference,
            'failures' => $failures,
            'status' => $failures === 0 && count($all) === 6 && $maxDifference === 0.0 ? 'PASS' : 'FAIL',
        ];
    }

    /** @return array<string, mixed> */
    private function compareScalar(string $legacyKey, string $legacyFunction, int $year, float $legacyValue, float $newValue): array
    {
        $difference = abs($legacyValue - $newValue);
        return [
            'legacy_key' => $legacyKey,
            'legacy_function' => $legacyFunction,
            'comparison_type' => 'scalar_annual_total',
            'year' => $year,
            'legacy_value' => $legacyValue,
            'new_value' => $newValue,
            'difference' => $difference,
            'max_difference' => $difference,
            'status' => $difference === 0.0 ? 'PASS' : 'FAIL',
        ];
    }
}
