<?php
/**
 * _costing_engine.php
 * Shared costing logic — identical to what costing.php runs.
 * Used by costing.php, list.php, financial_report.php.
 *
 * Provides: calcSegments(), calcJobCostSummary()
 */

if (!function_exists('calcSegments')) {
    function calcSegments(array $logs): array
    {
        $drivingMin = 0;
        $workingMin = 0;
        $pausedTravelMin = 0;
        $pausedWorkMin = 0;

        $events = [];
        foreach ($logs as $l) {
            $events[] = ['type' => $l['event_type'], 'ts' => strtotime($l['event_time'])];
        }
        usort($events, fn($a, $b) => $a['ts'] - $b['ts']);

        $state = 'idle';
        $segStart = null;

        foreach ($events as $ev) {
            $et = $ev['type'];
            $ts = $ev['ts'];
            $elapsed = $segStart !== null ? ($ts - $segStart) / 60.0 : 0;

            switch ($et) {
                case 'depart':
                    $state = 'driving';
                    $segStart = $ts;
                    break;
                case 'pause_travel':
                    if ($state === 'driving' && $segStart)
                        $drivingMin += $elapsed;
                    $state = 'paused_travel';
                    $segStart = $ts;
                    break;
                case 'resume_travel':
                    if ($state === 'paused_travel' && $segStart)
                        $pausedTravelMin += $elapsed;
                    $state = 'driving';
                    $segStart = $ts;
                    break;
                case 'arrive_site':
                    if ($state === 'driving' && $segStart)
                        $drivingMin += $elapsed;
                    $state = 'on_site';
                    $segStart = $ts;
                    break;
                case 'start_work':
                    $state = 'working';
                    $segStart = $ts;
                    break;
                case 'pause_work':
                    if ($state === 'working' && $segStart)
                        $workingMin += $elapsed;
                    $state = 'paused_work';
                    $segStart = $ts;
                    break;
                case 'resume_work':
                    if ($state === 'paused_work' && $segStart)
                        $pausedWorkMin += $elapsed;
                    $state = 'working';
                    $segStart = $ts;
                    break;
                case 'depart_site':
                    if ($state === 'working' && $segStart)
                        $workingMin += $elapsed;
                    $state = 'driving';
                    $segStart = $ts;
                    break;
                case 'arrive_base':
                    if ($state === 'driving' && $segStart)
                        $drivingMin += $elapsed;
                    if ($state === 'working' && $segStart)
                        $workingMin += $elapsed;
                    $state = 'idle';
                    $segStart = null;
                    break;
                case 'completed':
                case 'internal_complete':
                    if ($state === 'working' && $segStart)
                        $workingMin += $elapsed;
                    $state = 'idle';
                    $segStart = null;
                    break;
            }
        }

        return [
            'driving_min' => max(0, $drivingMin),
            'working_min' => max(0, $workingMin),
            'paused_travel_min' => max(0, $pausedTravelMin),
            'paused_work_min' => max(0, $pausedWorkMin),
        ];
    }
}

/**
 * Calculate the exact same summary as costing.php for a given job card ID.
 * Returns the same structure as costing.php's 'summary' key, plus net_profit.
 */
if (!function_exists('calcJobCostSummary')) {
    function calcJobCostSummary(PDO $db, int $jobCardId, float $defaultDays = 21.67, float $defaultHours = 8): array
    {

        // ── Fetch card with vehicle cost_per_km (same JOIN as costing.php) ──
        $jcStmt = $db->prepare("
        SELECT jc.*, v.cost_per_km, v.quote_rate_per_km
        FROM job_cards jc
        LEFT JOIN fleet_vehicles v ON v.id = jc.vehicle_id
        WHERE jc.id = ?
    ");
        $jcStmt->execute([$jobCardId]);
        $card = $jcStmt->fetch();
        if (!$card)
            return ['labour_cost' => 0, 'travel_cost' => 0, 'consumables_cost' => 0, 'slips_total' => 0, 'total_cost' => 0, 'net_profit' => 0];

        // ── Time logs ────────────────────────────────────────────
        $logsStmt = $db->prepare("
        SELECT tl.*, u.full_name, u.id AS uid
        FROM job_card_time_logs tl
        JOIN users u ON u.id = tl.user_id
        WHERE tl.job_card_id = ?
        ORDER BY tl.event_time ASC
    ");
        $logsStmt->execute([$jobCardId]);
        $timeLogs = $logsStmt->fetchAll();

        // ── Team members: lead (assigned_to) UNION extras ────────
        $teamStmt = $db->prepare("
        SELECT u.id AS user_id, u.full_name
        FROM users u
        WHERE u.id = (SELECT assigned_to FROM job_cards WHERE id = ?)
          AND u.id IS NOT NULL
        UNION
        SELECT jct.user_id, u2.full_name
        FROM job_card_technicians jct
        JOIN users u2 ON u2.id = jct.user_id
        WHERE jct.job_card_id = ?
    ");
        $teamStmt->execute([$jobCardId, $jobCardId]);
        $teamMembers = $teamStmt->fetchAll();

        // Fallback to time log users if no team assigned
        if (empty($teamMembers)) {
            $seen = [];
            foreach ($timeLogs as $l) {
                if (!isset($seen[$l['uid']])) {
                    $seen[$l['uid']] = true;
                    $teamMembers[] = ['user_id' => $l['uid'], 'full_name' => $l['full_name']];
                }
            }
        }

        // ── Hourly rates per team member (exact same query as costing.php) ──
        $techRates = [];
        foreach ($teamMembers as $tm) {
            $tid = $tm['user_id'];
            $rStmt = $db->prepare("
            SELECT es.basic_salary, es.salary_type, u.full_name,
                   COALESCE(e.days_per_month, ?) AS days_pm,
                   COALESCE(e.hours_per_day, ?)  AS hours_pd
            FROM users u
            LEFT JOIN employees e ON e.user_id = u.id
            LEFT JOIN employee_salaries es ON es.employee_id = e.id
            WHERE u.id = ?
            ORDER BY es.effective_date DESC LIMIT 1
        ");
            $rStmt->execute([$defaultDays, $defaultHours, $tid]);
            $r = $rStmt->fetch();
            $hourlyRate = 0;
            if ($r) {
                $dpm = (float) ($r['days_pm'] ?: $defaultDays);
                $hpd = (float) ($r['hours_pd'] ?: $defaultHours);
                if ($r['salary_type'] === 'hourly') {
                    $hourlyRate = (float) $r['basic_salary'];
                } elseif ($r['salary_type'] === 'monthly') {
                    $mh = $dpm * $hpd;
                    $hourlyRate = $mh > 0 ? round((float) $r['basic_salary'] / $mh, 2) : 0;
                } elseif ($r['salary_type'] === 'daily') {
                    $hourlyRate = $hpd > 0 ? round((float) $r['basic_salary'] / $hpd, 2) : 0;
                }
            }
            $techRates[$tid] = $hourlyRate;
        }

        // ── Shared timeline segments ─────────────────────────────
        $segs = calcSegments($timeLogs);
        $totalMin = $segs['driving_min'] + $segs['working_min']; // paused NOT included

        // ── Labour cost: shared time × each member's rate ────────
        $totalLabourCost = 0;
        foreach ($techRates as $rate) {
            $totalLabourCost += round(($totalMin / 60) * $rate, 2);
        }

        // ── Travel ───────────────────────────────────────────────
        $odoStart = (int) $card['odo_start'];
        $odoEnd = (int) $card['odo_end'];
        $kmTravelled = ($odoStart && $odoEnd) ? max(0, $odoEnd - $odoStart) : 0;
        $travelCost = round($kmTravelled * (float) ($card['cost_per_km'] ?? 0), 2);

        // ── Consumables ──────────────────────────────────────────
        $stStmt = $db->prepare("
        SELECT transaction_type, unit_cost, quantity
        FROM stock_transactions
        WHERE job_card_id = ? AND transaction_type IN ('issue_jobcard','return')
    ");
        $stStmt->execute([$jobCardId]);
        $consumablesCost = 0;
        foreach ($stStmt->fetchAll() as $si) {
            $mult = $si['transaction_type'] === 'return' ? -1 : 1;
            $consumablesCost += $mult * (float) $si['unit_cost'] * (float) $si['quantity'];
        }
        $consumablesCost = round($consumablesCost, 2);

        // ── Slips ─────────────────────────────────────────────────
        $slStmt = $db->prepare("SELECT COALESCE(SUM(amount), 0) FROM slips WHERE job_card_id = ?");
        $slStmt->execute([$jobCardId]);
        $slipsTotal = round((float) $slStmt->fetchColumn(), 2);

        // ── Total & nett ─────────────────────────────────────────
        $totalCost = round($totalLabourCost + $travelCost + $consumablesCost + $slipsTotal, 2);
        $invoice = (float) ($card['invoice_amount'] ?? 0);
        $netProfit = round($invoice - $totalCost, 2);

        return [
            'labour_cost' => round($totalLabourCost, 2),
            'travel_cost' => $travelCost,
            'consumables_cost' => $consumablesCost,
            'slips_total' => $slipsTotal,
            'total_cost' => $totalCost,
            'net_profit' => $netProfit,
        ];
    }
} // end function_exists calcJobCostSummary