<?php
/**
 * Overtime Intelligence API
 * Serves staffing data from ot-staffing.json with computed analytics.
 */
require_once __DIR__ . '/../config/auth.php';
requireLogin();

$action = $_GET['action'] ?? 'summary';
$dataFile = __DIR__ . '/../assets/data/ot-staffing.json';
$pbiFile = __DIR__ . '/../assets/data/ot-powerbi.json';

if (!file_exists($dataFile)) {
    jsonResponse(['error' => 'Data file not found'], 404);
}

$raw = json_decode(file_get_contents($dataFile), true);
$positions = $raw['positions'];
$dates = $raw['dates'];
$data = $raw['data'];
$salaryData = $raw['salary_data'];
$budget = $raw['budget'];
$contractMin = $raw['contract_minimum'] ?? null;
$rankMap = $salaryData['position_rank_map'];
$ranks = $salaryData['ranks'];

// Contract-derived baseline: 199 personnel x 24 hrs = 4,776 hrs/day
$contractDailyHours = $contractMin ? $contractMin['min_daily_hours'] : 4776;
$contractPersonnel = $contractMin ? $contractMin['min_personnel_per_shift'] : 199;

// Index ranks by code
$rankByCode = [];
foreach ($ranks as $r) $rankByCode[$r['rank']] = $r;

switch ($action) {

    case 'summary':
        // High-level stats for the dashboard
        $totalHours = 0;
        $totalDays = count($dates);
        $monthlyTotals = [];
        $positionTotals = array_fill(0, count($positions), 0);

        foreach ($data as $i => $row) {
            $total = end($row); // last element is total
            $totalHours += $total;
            $month = substr($dates[$i], 0, 7);
            $monthlyTotals[$month] = ($monthlyTotals[$month] ?? 0) + $total;

            foreach ($positions as $pi => $pos) {
                $positionTotals[$pi] += $row[$pi];
            }
        }

        // Contract-derived baseline (Article 37 + apparatus roster)
        $totalBaseline = $contractDailyHours * $totalDays;
        $otDelta = $totalHours - $totalBaseline;

        // Also keep P5 per position for position-level analysis
        $positionBaselines = [];
        foreach ($positions as $pi => $pos) {
            $vals = [];
            foreach ($data as $row) {
                if ($row[$pi] > 0) $vals[] = $row[$pi];
            }
            sort($vals);
            $p5 = !empty($vals) ? $vals[(int)(count($vals) * 0.05)] : 0;
            $positionBaselines[$pos] = $p5;
        }

        // Cost estimation
        $totalCost = 0;
        $rankCosts = [];
        foreach ($positions as $pi => $pos) {
            $rank = $rankMap[$pos] ?? 'FF1';
            $rate = $rankByCode[$rank]['true_ot'] ?? 76.65;
            $cost = $positionTotals[$pi] * $rate;
            $totalCost += $cost;
            $rankCosts[$rank] = ($rankCosts[$rank] ?? 0) + $cost;
        }

        // Position breakdown sorted by hours
        $posBreakdown = [];
        foreach ($positions as $pi => $pos) {
            $rank = $rankMap[$pos] ?? 'FF1';
            $rate = $rankByCode[$rank]['true_ot'] ?? 76.65;
            $baseline = $positionBaselines[$pos];
            $aboveBaseline = 0;
            foreach ($data as $row) {
                $aboveBaseline += max(0, $row[$pi] - $baseline);
            }
            $posBreakdown[] = [
                'position' => $pos,
                'rank' => $rank,
                'total_hours' => $positionTotals[$pi],
                'baseline_daily' => $baseline,
                'above_baseline' => $aboveBaseline,
                'ot_cost_est' => round($aboveBaseline * $rate),
                'pct_of_total' => round($positionTotals[$pi] / $totalHours * 100, 1),
            ];
        }
        usort($posBreakdown, fn($a, $b) => $b['total_hours'] - $a['total_hours']);

        jsonResponse([
            'total_days' => $totalDays,
            'date_range' => ['start' => end($dates), 'end' => $dates[0]],
            'total_hours' => $totalHours,
            'daily_avg' => round($totalHours / $totalDays),
            'baseline_daily' => $contractDailyHours,
            'baseline_personnel' => $contractPersonnel,
            'baseline_source' => 'Local 48 CBA Article 37 + CFD apparatus roster',
            'ot_delta_total' => $otDelta,
            'ot_delta_daily' => round($otDelta / $totalDays),
            'annualized_ot_hours' => round(max(0, $otDelta) / $totalDays * 365),
            'contract_minimum' => $contractMin,
            'positions' => $posBreakdown,
            'budget' => $budget,
            'salary_data' => $salaryData['ranks'],
        ]);
        break;

    case 'monthly':
        // Monthly breakdown for trend charts
        $monthly = [];
        foreach ($data as $i => $row) {
            $month = substr($dates[$i], 0, 7);
            if (!isset($monthly[$month])) {
                $monthly[$month] = ['month' => $month, 'total' => 0, 'days' => 0, 'positions' => array_fill(0, count($positions), 0)];
            }
            $monthly[$month]['total'] += end($row);
            $monthly[$month]['days']++;
            foreach ($positions as $pi => $pos) {
                $monthly[$month]['positions'][$pi] += $row[$pi];
            }
        }

        $result = [];
        foreach ($monthly as $m => $d) {
            $posData = [];
            foreach ($positions as $pi => $pos) {
                $rank = $rankMap[$pos] ?? 'FF1';
                $rate = $rankByCode[$rank]['true_ot'] ?? 76.65;
                $posData[$pos] = [
                    'hours' => $d['positions'][$pi],
                    'daily_avg' => round($d['positions'][$pi] / $d['days']),
                    'cost_est' => round($d['positions'][$pi] * $rate),
                ];
            }
            $avgRate = 87.50; // weighted average TRUE OT rate
            $result[] = [
                'month' => $m,
                'total_hours' => $d['total'],
                'days' => $d['days'],
                'daily_avg' => round($d['total'] / $d['days']),
                'cost_est' => round($d['total'] * $avgRate),
                'positions' => $posData,
            ];
        }
        usort($result, fn($a, $b) => strcmp($a['month'], $b['month']));
        jsonResponse(['monthly' => $result, 'positions' => $positions]);
        break;

    case 'position':
        // Daily data for a specific position
        $pos = $_GET['position'] ?? '';
        $pi = array_search($pos, $positions);
        if ($pi === false) {
            jsonResponse(['error' => 'Position not found', 'available' => $positions], 400);
        }

        $daily = [];
        $vals = [];
        foreach ($data as $i => $row) {
            $daily[] = ['date' => $dates[$i], 'hours' => $row[$pi]];
            if ($row[$pi] > 0) $vals[] = $row[$pi];
        }
        sort($vals);
        $p5 = $vals[(int)(count($vals) * 0.05)] ?? 0;
        $avg = count($vals) ? round(array_sum($vals) / count($vals)) : 0;

        $rank = $rankMap[$pos] ?? 'FF1';
        $rankInfo = $rankByCode[$rank] ?? null;

        jsonResponse([
            'position' => $pos,
            'rank' => $rank,
            'rank_info' => $rankInfo,
            'baseline' => $p5,
            'avg' => $avg,
            'min' => min($vals ?: [0]),
            'max' => max($vals ?: [0]),
            'daily' => $daily,
        ]);
        break;

    case 'breakeven':
        // Break-even calculator data
        $posHours = [];
        foreach ($positions as $pi => $pos) {
            $rank = $rankMap[$pos] ?? 'FF1';
            $vals = [];
            foreach ($data as $row) {
                if ($row[$pi] > 0) $vals[] = $row[$pi];
            }
            sort($vals);
            $p5 = !empty($vals) ? $vals[(int)(count($vals) * 0.05)] : 0;
            $aboveBaseline = 0;
            foreach ($data as $row) {
                $aboveBaseline += max(0, $row[$pi] - $p5);
            }
            $totalDays = count($dates);
            $annualOtHours = round($aboveBaseline / $totalDays * 365);

            if (!isset($posHours[$rank])) {
                $posHours[$rank] = ['hours' => 0, 'positions' => []];
            }
            $posHours[$rank]['hours'] += $annualOtHours;
            $posHours[$rank]['positions'][] = $pos;
        }

        $breakeven = [];
        foreach ($ranks as $r) {
            $code = $r['rank'];
            $otHrs = $posHours[$code]['hours'] ?? 0;
            $otCost = $otHrs * $r['true_ot'];
            $hireEquiv = $r['hire_cost'] > 0 ? round($otCost / $r['hire_cost'], 1) : 0;
            $breakeven[] = [
                'rank' => $code,
                'title' => $r['title'],
                'base_salary' => $r['base'],
                'hire_cost' => $r['hire_cost'],
                'ot_rate' => $r['ot_rate'],
                'true_ot_rate' => $r['true_ot'],
                'breakeven_hours' => $r['breakeven'],
                'annual_ot_hours' => $otHrs,
                'annual_ot_cost' => round($otCost),
                'hire_equivalents' => $hireEquiv,
                'positions' => $posHours[$code]['positions'] ?? [],
            ];
        }

        jsonResponse(['breakeven' => $breakeven, 'budget' => $budget]);
        break;

    case 'raw':
        // Full raw data for client-side processing
        jsonResponse([
            'positions' => $positions,
            'dates' => $dates,
            'data' => $data,
            'salary_data' => $salaryData,
            'budget' => $budget,
        ]);
        break;

    case 'powerbi':
        // Actual OT data from Power BI (Manpower + Internal OT + Leave)
        if (!file_exists($pbiFile)) {
            jsonResponse(['error' => 'Power BI data not available'], 404);
        }
        $pbi = json_decode(file_get_contents($pbiFile), true);
        jsonResponse($pbi);
        break;

    case 'burndown':
        $bdFile = __DIR__ . '/../assets/data/ot-burndown.json';
        if (!file_exists($bdFile)) {
            jsonResponse(['error' => 'Burn-down data not available'], 404);
        }
        jsonResponse(json_decode(file_get_contents($bdFile), true));
        break;

    case 'executive':
        $exFile = __DIR__ . '/../assets/data/ot-executive.json';
        if (!file_exists($exFile)) {
            jsonResponse(['error' => 'Executive data not available'], 404);
        }
        jsonResponse(json_decode(file_get_contents($exFile), true));
        break;

    default:
        jsonResponse(['error' => 'Unknown action', 'actions' => ['summary', 'monthly', 'position', 'breakeven', 'raw', 'powerbi', 'burndown', 'executive']]);
}
