<?php
require_auth();
$method = $_SERVER['REQUEST_METHOD'];
$d = input();
$id = (int)($d['id'] ?? 0);
$action = $d['action'] ?? null;
$booking_id = (int)($d['booking_id'] ?? 0);

if ($method === 'GET' && $action === 'summary') {
    require_permission('finance.view');
    if (!$booking_id) json_error('booking_id required', 422);
    $b = db()->prepare('SELECT b.*, p.name AS property_name, r.room_number, rt.name AS room_type_name
        FROM bookings b
        JOIN properties p ON p.id = b.property_id
        LEFT JOIN rooms r ON r.id = b.room_id
        LEFT JOIN room_types rt ON rt.id = b.room_type_id
        WHERE b.id = ?');
    $b->execute([$booking_id]);
    $booking = $b->fetch();
    if (!$booking) json_error('Booking not found', 404);
    $c = db()->prepare('SELECT * FROM folio_charges WHERE booking_id = ? ORDER BY created_at DESC');
    $c->execute([$booking_id]);
    $charges = $c->fetchAll();
    $p = db()->prepare('SELECT * FROM payments WHERE booking_id = ? ORDER BY created_at DESC');
    $p->execute([$booking_id]);
    $payments = $p->fetchAll();
    $totalCharges = 0; $totalTax = 0;
    foreach ($charges as $ch) {
        if (!$ch['voided']) { $totalCharges += (float)$ch['amount']; $totalTax += (float)$ch['tax_amount']; }
    }
    $roomTotal = (float)$booking['total'];
    $paid = (float)$booking['amount_paid'];
    $extrasNet = $totalCharges;
    $grandTotal = $roomTotal + $extrasNet + $totalTax;
    $balance = $grandTotal - $paid;
    json_ok([
        'booking' => $booking,
        'charges' => $charges,
        'payments' => $payments,
        'totals' => [
            'room_total' => $roomTotal,
            'extras_total' => $extrasNet,
            'tax_total' => $totalTax,
            'grand_total' => $grandTotal,
            'paid' => $paid,
            'balance_due' => max(0, $balance),
        ]
    ]);
}

if ($method === 'GET') {
    require_permission('finance.view');
    if (!$booking_id) json_error('booking_id required', 422);
    $s = db()->prepare('SELECT fc.*, u.name AS posted_by_name FROM folio_charges fc
        LEFT JOIN users u ON u.id = fc.posted_by
        WHERE fc.booking_id = ? ORDER BY fc.created_at DESC');
    $s->execute([$booking_id]);
    json_ok($s->fetchAll());
}

csrf_check();

if ($method === 'POST') {
    require_permission('finance.manage');
    $errors = v_required($d, ['booking_id','description','amount']);
    if ($errors) json_error('Validation failed', 422, $errors);
    $qty = (float)($d['quantity'] ?? 1);
    $unit = (float)($d['unit_price'] ?? $d['amount']);
    $amt = isset($d['amount']) ? (float)$d['amount'] : ($qty * $unit);
    $tax = (float)($d['tax_amount'] ?? 0);
    db()->prepare('INSERT INTO folio_charges
        (booking_id, charge_type, description, quantity, unit_price, amount, tax_amount, posted_by, posted_at, notes)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), ?)')->execute([
        (int)$d['booking_id'],
        $d['charge_type'] ?? 'other',
        v_str($d, 'description', 255),
        $qty, $unit, $amt, $tax,
        current_user()['id'],
        $d['notes'] ?? null
    ]);
    $newId = (int)db()->lastInsertId();
    db()->prepare('UPDATE bookings SET extras_total = (SELECT COALESCE(SUM(amount + tax_amount),0) FROM folio_charges WHERE booking_id = ? AND voided = 0) WHERE id = ?')->execute([(int)$d['booking_id'], (int)$d['booking_id']]);
    audit_log('folio.post', 'folio_charge', $newId);
    json_ok(['id' => $newId], 'Charge posted');
}

if (($method === 'PUT' || $method === 'PATCH') && $action === 'void') {
    require_permission('finance.manage');
    if (!$id) json_error('id required', 422);
    db()->prepare('UPDATE folio_charges SET voided=1, voided_at=NOW(), voided_by=? WHERE id=?')->execute([current_user()['id'], $id]);
    $bk = db()->prepare('SELECT booking_id FROM folio_charges WHERE id=?');
    $bk->execute([$id]);
    if ($row = $bk->fetch()) {
        db()->prepare('UPDATE bookings SET extras_total = (SELECT COALESCE(SUM(amount + tax_amount),0) FROM folio_charges WHERE booking_id = ? AND voided = 0) WHERE id = ?')->execute([(int)$row['booking_id'], (int)$row['booking_id']]);
    }
    audit_log('folio.void', 'folio_charge', $id);
    json_ok([], 'Charge voided');
}

json_error('Method not allowed', 405);
