<?php
/**
 * Shared labour cost calculation helper.
 * Used by list.php and financial_report.php to match costing.php exactly.
 */

/**
 * Run the same state-machine segment calculator as costing.php.
 * Returns billable minutes: driving + working (pauses excluded).
 */
function calcBillableMinutes(array $logs): float {
    $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 max(0, $drivingMin) + max(0, $workingMin);
}

/**
 * Get total combined hourly rate for all team members on a job.
 * Uses UNION (deduplicated) so lead tech is never double-counted.
 */
function getTeamHourlyRate(PDO $db, int $jobCardId, float $defaultDays, float $defaultHours): float {
    $rateStmt = $db->prepare("
        SELECT COALESCE(es.basic_salary, 0) AS salary,
               COALESCE(es.salary_type, 'monthly') AS salary_type,
               COALESCE(e.days_per_month, :dpm1) AS dpm,
               COALESCE(e.hours_per_day,  :hpd1) AS hpd
        FROM users u2
        LEFT JOIN employees e   ON e.user_id = u2.id
        LEFT JOIN employee_salaries es ON es.employee_id = e.id
            AND es.effective_date = (SELECT MAX(x.effective_date) FROM employee_salaries x WHERE x.employee_id = e.id)
        WHERE u2.id = (SELECT assigned_to FROM job_cards WHERE id = :jid1)
          AND u2.id IS NOT NULL
        UNION
        SELECT COALESCE(es2.basic_salary, 0),
               COALESCE(es2.salary_type, 'monthly'),
               COALESCE(e2.days_per_month, :dpm2),
               COALESCE(e2.hours_per_day,  :hpd2)
        FROM job_card_technicians jct
        JOIN users u3 ON u3.id = jct.user_id
        LEFT JOIN employees e2   ON e2.user_id = u3.id
        LEFT JOIN employee_salaries es2 ON es2.employee_id = e2.id
            AND es2.effective_date = (SELECT MAX(x2.effective_date) FROM employee_salaries x2 WHERE x2.employee_id = e2.id)
        WHERE jct.job_card_id = :jid2
    ");
    $rateStmt->execute([
        ':dpm1' => $defaultDays,  ':hpd1' => $defaultHours, ':jid1' => $jobCardId,
        ':dpm2' => $defaultDays,  ':hpd2' => $defaultHours, ':jid2' => $jobCardId,
    ]);
    $rates = $rateStmt->fetchAll();

    $total = 0.0;
    foreach ($rates as $r) {
        $dpm = (float)($r['dpm'] ?: $defaultDays);
        $hpd = (float)($r['hpd'] ?: $defaultHours);
        if ($r['salary_type'] === 'hourly') {
            $total += (float)$r['salary'];
        } elseif ($r['salary_type'] === 'monthly') {
            $mh = $dpm * $hpd;
            $total += $mh > 0 ? (float)$r['salary'] / $mh : 0;
        } elseif ($r['salary_type'] === 'daily') {
            $total += $hpd > 0 ? (float)$r['salary'] / $hpd : 0;
        }
    }
    return $total;
}

/**
 * Calculate full job cost breakdown matching the costing tab exactly.
 * Returns array: labour_cost, travel_cost, stock_cost, slips_cost, total_cost, net_profit
 */
function calcJobCost(PDO $db, array $row, float $defaultDays, float $defaultHours): array {
    $jid = (int)$row['id'];

    // ── Time logs for state machine ──────────────────────────
    $tlStmt = $db->prepare("SELECT event_type, event_time FROM job_card_time_logs WHERE job_card_id = ? ORDER BY event_time ASC");
    $tlStmt->execute([$jid]);
    $logs = $tlStmt->fetchAll();

    $billableMin     = calcBillableMinutes($logs);
    $billableHours   = $billableMin / 60.0;
    $teamHourlyRate  = getTeamHourlyRate($db, $jid, $defaultDays, $defaultHours);
    $labourCost      = round($billableHours * $teamHourlyRate, 2);

    // ── Travel ───────────────────────────────────────────────
    $odoStart   = (int)($row['odo_start'] ?? 0);
    $odoEnd     = (int)($row['odo_end']   ?? 0);
    $km         = ($odoStart && $odoEnd) ? max(0, $odoEnd - $odoStart) : 0;
    $costPerKm  = 0.0;
    if ($row['vehicle_id'] ?? null) {
        $vStmt = $db->prepare("SELECT cost_per_km FROM fleet_vehicles WHERE id = ?");
        $vStmt->execute([$row['vehicle_id']]);
        $v = $vStmt->fetch();
        if ($v) $costPerKm = (float)$v['cost_per_km'];
    }
    $travelCost = round($km * $costPerKm, 2);

    // ── Stock / consumables ───────────────────────────────────
    $stStmt = $db->prepare("
        SELECT SUM(CASE WHEN transaction_type='return' THEN -(unit_cost*quantity) ELSE unit_cost*quantity END) AS total
        FROM stock_transactions
        WHERE job_card_id = ? AND transaction_type IN ('issue_jobcard','return')
    ");
    $stStmt->execute([$jid]);
    $stockCost = round((float)($stStmt->fetchColumn() ?? 0), 2);

    // ── Slips ─────────────────────────────────────────────────
    $slStmt = $db->prepare("SELECT COALESCE(SUM(amount), 0) FROM slips WHERE job_card_id = ?");
    $slStmt->execute([$jid]);
    $slipsCost = round((float)$slStmt->fetchColumn(), 2);

    // ── Total & net profit ────────────────────────────────────
    $totalCost  = round($labourCost + $travelCost + $stockCost + $slipsCost, 2);
    $invoice    = (float)($row['invoice_amount'] ?? 0);
    $netProfit  = round($invoice - $totalCost, 2);

    return [
        'labour_cost'    => $labourCost,
        'travel_cost'    => $travelCost,
        'stock_cost'     => $stockCost,
        'slips_cost'     => $slipsCost,
        'total_cost'     => $totalCost,
        'net_profit'     => $netProfit,
        'billable_hours' => round($billableHours, 2),
    ];
}