<?php

function normalizarModeloDashboard(?string $modelo): string
{
    $m = strtolower(trim((string)$modelo));
    if ($m === '') {
        return 'orcamento';
    }
    return $m;
}

function montarVisaoConsolidadaPorModelo(array $kpisVariaveis): array
{
    $periodos = [
        'mes' => ['orc' => 'orcMes', 'real' => 'realMes', 'projValor' => 'projMesValor', 'projPerc' => 'projMesPerc'],
        'trimestre' => ['orc' => 'orcTrim', 'real' => 'realTrim', 'projValor' => 'projTrimValor', 'projPerc' => 'projTrimPerc'],
        'ano' => ['orc' => 'orcAno', 'real' => 'realAno', 'projValor' => 'projAnoValor', 'projPerc' => 'projAnoPerc'],
    ];

    $ordemModelos = ['meta', 'submeta', 'resultado', 'orcamento'];

    $out = [];
    foreach ($ordemModelos as $m) {
        $out[$m] = [];
        foreach (array_keys($periodos) as $p) {
            $out[$m][$p] = [
                'modelo' => $m,
                'periodo' => $p,
                'total_orc' => 0.0,
                'total_real' => 0.0,
                'perc_total' => 0.0,
                'vars' => [],
                'melhor' => null,
                'pior' => null,
                'criticos_qtd' => 0,
            ];
        }
    }

    foreach ($kpisVariaveis as $kv) {
        $modelo = normalizarModeloDashboard($kv['modelo'] ?? null);
        if (!isset($out[$modelo])) {
            // Ignora modelos desconhecidos para manter o contrato de 4 blocos
            continue;
        }

        foreach ($periodos as $p => $map) {
            $orc = (float)($kv[$map['orc']] ?? 0.0);
            $real = (float)($kv[$map['real']] ?? 0.0);
            $projValor = $kv[$map['projValor']] ?? null;
            $projPerc = $kv[$map['projPerc']] ?? null;

            // Modelo ORÇAMENTO: normaliza sinal (débito pode vir negativo)
            if ($modelo === 'orcamento') {
                $orc = abs($orc);
                $real = abs($real);
                if ($projValor !== null) {
                    $projValor = abs((float)$projValor);
                }
            }

            $out[$modelo][$p]['total_orc'] += $orc;
            $out[$modelo][$p]['total_real'] += $real;

            $out[$modelo][$p]['vars'][] = [
                'id' => (int)($kv['id'] ?? 0),
                'nome' => (string)($kv['nome'] ?? ''),
                'orc' => $orc,
                'real' => $real,
                'perc' => ($orc > 0.0) ? ($real / $orc) : 0.0,
                'restante' => max(0.0, $orc - $real),
                'proj_valor' => ($projValor === null) ? null : (float)$projValor,
                'proj_perc' => ($projPerc === null) ? null : (float)$projPerc,
            ];
        }
    }

    foreach ($ordemModelos as $modelo) {
        foreach (array_keys($periodos) as $p) {
            $bucket = &$out[$modelo][$p];

            if ($bucket['total_orc'] > 0.0) {
                $bucket['perc_total'] = $bucket['total_real'] / $bucket['total_orc'];
            } else {
                $bucket['perc_total'] = 0.0;
            }

            // Ordenação conforme regra
            usort($bucket['vars'], function ($a, $b) use ($modelo) {
                $pa = (float)($a['perc'] ?? 0.0);
                $pb = (float)($b['perc'] ?? 0.0);
                if ($pa === $pb) return 0;

                if ($modelo === 'orcamento') {
                    // Maior -> menor
                    return ($pa < $pb) ? 1 : -1;
                }

                // Menor -> maior
                return ($pa < $pb) ? -1 : 1;
            });

            // Melhor / pior
            $melhor = null;
            $pior = null;
            foreach ($bucket['vars'] as $v) {
                if ($melhor === null || (float)$v['perc'] > (float)$melhor['perc']) {
                    $melhor = $v;
                }
                if ($pior === null || (float)$v['perc'] < (float)$pior['perc']) {
                    $pior = $v;
                }
            }
            $bucket['melhor'] = $melhor ? ['id' => $melhor['id'], 'nome' => $melhor['nome'], 'perc' => (float)$melhor['perc']] : null;
            $bucket['pior'] = $pior ? ['id' => $pior['id'], 'nome' => $pior['nome'], 'perc' => (float)$pior['perc']] : null;

            // Contagem de críticos
            $criticos = 0;
            foreach ($bucket['vars'] as $v) {
                $perc = (float)($v['perc'] ?? 0.0);
                if ($modelo === 'orcamento') {
                    if ($perc >= 0.85) {
                        $criticos++;
                    }
                } else {
                    if ($perc < 0.80) {
                        $criticos++;
                    }
                }
            }
            $bucket['criticos_qtd'] = $criticos;
        }
    }

    return $out;
}

function montarKpisBasicosFromDashboards(
    array $dashboards,
    int $mesAtual,
    int $anoref,
    array $mesesSel,
    int $mesSistema,
    int $anoSistema,
    int $trimestreFiltro,
    int $diaCorrente,
    int $ultimoDiaMesCorrente,
    int $diasRestantesMesCorrente,
    int $diaAnoAtualGlobal,
    int $diasRestantesAno,
    int $qtdFeriadosMes,
    bool $feriadoDiaUtil
): array {
    $kpis = [];

    foreach ($dashboards as $dash) {
        if (isset($dash['tipo']) && (string)$dash['tipo'] !== 'Dashboard') {
            continue;
        }
        if (empty($dash['secoes'])) {
            continue;
        }

        $modeloDash = normalizarModeloDashboard($dash['modelo'] ?? null);
        $isOrcamento = ($modeloDash === 'orcamento');

        $orcAnoTotal = 0.0;
        $realAnoTotal = 0.0;
        $orcMesTotal = 0.0;
        $realMesTotal = 0.0;
        $orcTrimTotal = 0.0;
        $realTrimTotal = 0.0;

        $projAnoTotal = 0.0;
        $projMesTotal = 0.0;
        $projTrimTotal = 0.0;

        foreach ($dash['secoes'] as $secResumo) {
            $anoResumo = $secResumo['ano'] ?? null;
            if (is_array($anoResumo)) {
                $orcAnoTotal += (float)($anoResumo['orcado'] ?? 0.0);
                $realAnoTotal += (float)($anoResumo['realizado'] ?? 0.0);
                $projAnoTotal += (float)($anoResumo['projValor'] ?? 0.0);
            }

            $mesResumo = $secResumo['mes'] ?? null;
            if (is_array($mesResumo)) {
                $orcMesTotal += (float)($mesResumo['orcado'] ?? 0.0);
                $realMesTotal += (float)($mesResumo['realizado'] ?? 0.0);
                $projMesTotal += (float)($mesResumo['projValor'] ?? 0.0);
            }

            $trimResumo = $secResumo['trimestre'] ?? null;
            if (is_array($trimResumo)) {
                $orcTrimTotal += (float)($trimResumo['orcado'] ?? 0.0);
                $realTrimTotal += (float)($trimResumo['realizado'] ?? 0.0);
                $projTrimTotal += (float)($trimResumo['projValor'] ?? 0.0);
            }
        }

        // Modelo ORÇAMENTO: normaliza sinal (débito pode vir negativo)
        if ($isOrcamento) {
            $orcAnoTotal = abs($orcAnoTotal);
            $realAnoTotal = abs($realAnoTotal);
            $orcMesTotal = abs($orcMesTotal);
            $realMesTotal = abs($realMesTotal);
            $orcTrimTotal = abs($orcTrimTotal);
            $realTrimTotal = abs($realTrimTotal);
        }

        // Cálculo de percentuais: diferente para Orçamento vs Meta/Submeta
        if ($isOrcamento) {
            // Orçamento: atingPerc = consumo (pelo mês)
            $atingMesPerc   = ($orcMesTotal != 0.0) ? ($realMesTotal / $orcMesTotal) : 0.0;
            $restanteMesPerc = max(0.0, 1.0 - $atingMesPerc);
        } else {
            // Meta/Submeta: atingPerc = alcance (pelo ano)
            $atingMesPerc   = ($orcAnoTotal != 0.0) ? ($realAnoTotal / $orcAnoTotal) : 0.0;
            $restanteMesPerc = max(0.0, 1.0 - $atingMesPerc);
        }

        // Projeções: usar os valores já calculados no serviço (respeita multi-mês, ano/trimestre correntes, etc.)
        $projMesValor = (float)$projMesTotal;
        $projMesPerc  = ($orcMesTotal != 0.0) ? ($projMesValor / $orcMesTotal) : 0.0;

        $projTrimValor = (float)$projTrimTotal;
        $projTrimPerc  = ($orcTrimTotal != 0.0) ? ($projTrimValor / $orcTrimTotal) : 0.0;

        $projAnoValor = (float)$projAnoTotal;
        $projAnoPerc  = ($orcAnoTotal != 0.0) ? ($projAnoValor / $orcAnoTotal) : 0.0;

        $kpis[] = [
            'id'            => (int)($dash['cdvariavel'] ?? 0),
            'nome'          => (string)($dash['nome'] ?? ''),
            'modelo'        => (string)($dash['modelo'] ?? 'orcamento'),
            'grafico'       => $dash['grafico'] ?? false,
            'fl_origem'     => !empty($dash['fl_origem']),
            'fl_agregar_calc' => !empty($dash['fl_agregar_calc']),
            'orcAno'        => $orcAnoTotal,
            'realAno'       => $realAnoTotal,
            'projAnoValor'  => (float)$projAnoValor,
            'projAnoPerc'   => (float)$projAnoPerc,
            'orcMes'        => $orcMesTotal,
            'realMes'       => $realMesTotal,
            'atingPerc'     => (float)$atingMesPerc,
            'restantePerc'  => (float)$restanteMesPerc,
            'projMesValor'  => (float)$projMesValor,
            'projMesPerc'   => (float)$projMesPerc,
            'orcTrim'       => $orcTrimTotal,
            'realTrim'      => $realTrimTotal,
            'projTrimValor' => (float)$projTrimValor,
            'projTrimPerc'  => (float)$projTrimPerc,
        ];
    }

    return $kpis;
}
