<?php
declare(strict_types=1);
/**
 * modules/bookings/complete.php
 *
 * Popup-driven booking completion with partial payments + pending payments.
 *
 * - "Paid & Complete" inserts only the paid amount into transactions (CHAUF_INCOME).
 *   If paid < total -> inserts a pending_payments row (type='client') for the balance.
 * - "Complete Unpaid" inserts a pending_payments row (type='client') for the full amount (no transactions).
 * - Commission is computed & shown for information only and NOT posted here.
 * - Idempotent: removes previous CHAUF_INCOME and pending_payments for the booking before insert.
 *
 * Requirements:
 *  - config/functions.php provides db(), csrf_token(), csrf_verify(), require_role(), current_user(), audit_log(), url_modules(), url_public()
 */

require_once dirname(__DIR__, 2) . '/config/functions.php';
require_role(['Admin','Ops','Accounts']);

$user = current_user();
$cid  = (int)($user['company_id'] ?? 0);
if ($cid <= 0) redirect(url_public('login.php'));

/* helper: test table existence */
function table_exists(string $table): bool {
  try {
    db()->query("SELECT 1 FROM `{$table}` LIMIT 1");
    return true;
  } catch (Throwable $e) {
    return false;
  }
}

/* booking id (GET for popup open, POST for form submit) */
$bid = (int)($_GET['id'] ?? $_POST['id'] ?? 0);
if ($bid <= 0) redirect(url_modules('bookings/list.php'));

/* Load booking + partner details (for commission calc/display) */
$sel = db()->prepare("
  SELECT b.*, p.commission_type AS partner_commission_type, p.commission_value AS partner_commission_value
  FROM bookings b
  LEFT JOIN partners p ON p.id = b.partner_id
  WHERE b.id = :id AND b.company_id = :cid
  LIMIT 1
");
$sel->execute([':id'=>$bid, ':cid'=>$cid]);
$booking = $sel->fetch();
if (!$booking) redirect(url_modules('bookings/list.php'));

/* Derive totals */
$clientTotal = (float)($booking['total_client_price'] ?? 0.0)
             + (float)($booking['client_parking_fee'] ?? 0.0)
             + (float)($booking['client_waiting_fee'] ?? 0.0);

$driverTotal = (float)($booking['total_driver_price'] ?? 0.0)
             + (float)($booking['driver_parking_fee'] ?? 0.0)
             + (float)($booking['driver_waiting_fee'] ?? 0.0);

/* Commission calculation (for display only) */
$commission = (float)($booking['partner_commission_amount'] ?? 0.0);
if ($commission <= 0 && !empty($booking['partner_id'])) {
  $ctype = (string)($booking['partner_commission_type'] ?? '');
  $cval  = (float)($booking['partner_commission_value'] ?? 0.0);
  if ($ctype === 'fixed') {
    $commission = max(0.0, $cval);
  } elseif ($ctype === 'percent') {
    $commission = max(0.0, ($cval / 100.0) * (float)($booking['total_client_price'] ?? 0.0));
  } else {
    $commission = 0.0;
  }
}

/* prepare some display variables */
$ref = (string)($booking['booking_ref'] ?? ('#'.$bid));
$pickupDate = (string)($booking['pickup_date'] ?? '');
$txDateDefault = $pickupDate !== '' ? $pickupDate : date('Y-m-d');

/* Ensure pending_payments table exists (best-effort) -- includes 'type' ENUM */
if (!table_exists('pending_payments')) {
  try {
    db()->exec("
      CREATE TABLE IF NOT EXISTS pending_payments (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        company_id INT UNSIGNED NOT NULL,
        booking_id BIGINT UNSIGNED NOT NULL,
        booking_ref VARCHAR(128) NOT NULL,
        `type` ENUM('client','driver','commission') NOT NULL DEFAULT 'client',
        total_due DECIMAL(10,2) NOT NULL DEFAULT 0.00,
        amount_paid DECIMAL(10,2) NOT NULL DEFAULT 0.00,
        balance_due DECIMAL(10,2) NOT NULL DEFAULT 0.00,
        status VARCHAR(32) NOT NULL DEFAULT 'pending',
        created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        KEY idx_company_booking (company_id, booking_id),
        KEY idx_type (`type`)
      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
    ");
  } catch (Throwable $e) {
    // ignore creation failure; we'll handle insert errors later
  }
}

/* ---------- Handle POST (form submit) ---------- */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
  try {
    csrf_verify((string)($_POST['csrf'] ?? ''));

    $action = (string)($_POST['action']);
    if (!in_array($action, ['paid','unpaid'], true)) {
      throw new RuntimeException('Invalid action.');
    }

    $pdo = db();
    $pdo->beginTransaction();

    $hasTx = table_exists('transactions');

    // Idempotency: remove prior CHAUF_INCOME tx for this booking (we will reinsert only what's relevant)
    if ($hasTx) {
      $del = $pdo->prepare("
        DELETE FROM transactions
         WHERE company_id = :cid
           AND booking_id = :bid
           AND account_code = 'CHAUF_INCOME'
      ");
      $del->execute([':cid'=>$cid, ':bid'=>$bid]);
    }

    // Remove any previous pending_payments rows for this booking (all types) to avoid duplicates
    if (table_exists('pending_payments')) {
      $delPend = $pdo->prepare("DELETE FROM pending_payments WHERE company_id=:cid AND booking_id=:bid");
      $delPend->execute([':cid'=>$cid, ':bid'=>$bid]);
    }

    $amountPaid = 0.0;
    $balance = 0.0;
    $paidAt = (string)($_POST['paid_at'] ?? date('Y-m-d H:i'));

    if ($action === 'paid') {
      // sanitize & validate amount
      $amountPaid = (float)($_POST['amount_paid'] ?? 0.0);
      if ($amountPaid <= 0.0) {
        throw new RuntimeException('Amount paid must be greater than zero.');
      }
      // disallow paying more than client total here (you can extend to allow credit if desired)
      if ($amountPaid > $clientTotal) {
        throw new RuntimeException('Amount paid cannot exceed client total.');
      }

      // Insert CHAUF_INCOME only for the amount actually paid
      if ($hasTx) {
        $ins = $pdo->prepare("
          INSERT INTO transactions
            (company_id, date, account_code, segment, type, amount, booking_id, reference, notes, created_at)
          VALUES
            (:cid, DATE(:paid_at), 'CHAUF_INCOME', 'Chauffeur', 'income', :amt, :bid, :ref, :note, NOW())
        ");
        $ins->execute([
          ':cid'     => $cid,
          ':paid_at' => $paidAt,
          ':amt'     => $amountPaid,
          ':bid'     => $bid,
          ':ref'     => $ref,
          ':note'    => "Booking {$ref} — client payment"
        ]);
      }

      // If partial, insert pending_payments for the client balance (type='client')
      if ($amountPaid < $clientTotal) {
        $balance = round($clientTotal - $amountPaid, 2);
        if (table_exists('pending_payments')) {
          $insPend = $pdo->prepare("
            INSERT INTO pending_payments
              (company_id, booking_id, booking_ref, `type`, total_due, amount_paid, balance_due, status, created_at)
            VALUES
              (:cid,:bid,:ref,'client',:total,:paid,:bal,'pending', NOW())
          ");
          $insPend->execute([
            ':cid'  => $cid,
            ':bid'  => $bid,
            ':ref'  => $ref,
            ':total'=> $clientTotal,
            ':paid' => $amountPaid,
            ':bal'  => $balance
          ]);
        }
      }

    } else { // unpaid
      // Full amount goes to pending_payments (type='client'), no transactions
      $balance = round($clientTotal, 2);
      if (table_exists('pending_payments')) {
        $insPend = $pdo->prepare("
          INSERT INTO pending_payments
            (company_id, booking_id, booking_ref, `type`, total_due, amount_paid, balance_due, status, created_at)
          VALUES
            (:cid,:bid,:ref,'client',:total,0,:bal,'pending', NOW())
        ");
        $insPend->execute([
          ':cid' => $cid,
          ':bid' => $bid,
          ':ref' => $ref,
          ':total' => $clientTotal,
          ':bal' => $balance
        ]);
      }
    }

    // Update booking status -> Completed
    $upd = $pdo->prepare("
      UPDATE bookings
         SET status = 'Completed', updated_at = NOW()
       WHERE id = :id AND company_id = :cid
    ");
    $upd->execute([':id'=>$bid, ':cid'=>$cid]);

    audit_log('booking.complete', 'booking', $bid, [
      'booking_ref' => $ref,
      'action'      => $action,
      'amount_paid' => $amountPaid,
      'balance'     => $balance,
      'tx_posted'   => $hasTx && $action === 'paid' ? 1 : 0
    ]);

    $pdo->commit();

    // Redirect back to bookings list (close popup flow not required here)
    redirect(url_modules('bookings/list.php') . '?ok=completed');


    // Success: close popup & refresh opener (if present)
    echo '<!doctype html><html><head><meta charset="utf-8"><title>Done</title></head><body>';
    echo '<div style="font-family:Arial,Helvetica,sans-serif;margin:30px;text-align:center">';
    echo '<h2 style="margin-bottom:6px">Booking Completed</h2>';
    echo '<p style="color:#444;margin:6px">Reference: <strong>'.htmlspecialchars($ref).'</strong></p>';
    if ($action === 'paid') {
      echo '<p style="color:green;margin:6px">Paid: £'.number_format($amountPaid,2).'</p>';
      if ($balance > 0) echo '<p style="color:orange;margin:6px">Balance pending: £'.number_format($balance,2).'</p>';
    } else {
      echo '<p style="color:orange;margin:6px">Marked completed (unpaid). Balance pending: £'.number_format($balance,2).'</p>';
    }
    echo '<p style="margin-top:12px"><button onclick="closeWindow()" style="padding:8px 12px;border-radius:6px;border:1px solid #ccc;background:#f8f9fa;cursor:pointer">Close</button></p>';
    echo '</div>';
    echo '<script>
      function closeWindow(){
        try { if (window.opener && !window.opener.closed) window.opener.location.reload(); } catch(e){}
        try { window.close(); } catch(e){}
      }
      // auto-close after 1.2s
      setTimeout(closeWindow, 1200);
    </script>';
    echo '</body></html>';
    exit;
  } catch (Throwable $e) {
    if (isset($pdo) && $pdo->inTransaction()) $pdo->rollBack();
    $msg = (defined('APP_ENV') && APP_ENV === 'dev') ? $e->getMessage() : 'Unable to complete booking.';
    // show a simple error page inside popup
    echo '<!doctype html><html><head><meta charset="utf-8"><title>Error</title></head><body>';
    echo '<div style="font-family:Arial,Helvetica,sans-serif;margin:30px">';
    echo '<h2 style="color:#c00">Error</h2>';
    echo '<pre style="background:#f8f9fa;border:1px solid #eee;padding:10px">'.htmlspecialchars($msg).'</pre>';
    echo '<p><button onclick="window.history.back()">Back</button></p>';
    echo '</div></body></html>';
    exit;
  }
}

/* ---------- Show popup form (GET) ---------- */
$csrf = csrf_token();
?>
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Complete Booking <?=htmlspecialchars($ref)?></title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <style>
    body{font-family:Inter,system-ui,Arial,Helvetica,sans-serif;background:#f4f6f8;margin:0;padding:24px;color:#1f2937}
    .card{max-width:640px;margin:0 auto;background:#fff;padding:20px;border-radius:10px;box-shadow:0 6px 20px rgba(15,23,42,0.06)}
    h1{font-size:18px;margin:0 0 8px}
    .meta{color:#6b7280;margin-bottom:12px}
    .row{display:flex;gap:12px;flex-wrap:wrap;margin-top:8px}
    .box{flex:1;min-width:160px;background:#f8fafc;border-radius:8px;padding:10px}
    label{display:block;font-size:13px;color:#374151;margin-bottom:6px}
    input[type=number], input[type=datetime-local], input[type=text]{width:100%;padding:8px;border-radius:8px;border:1px solid #e6e9ef}
    .actions{display:flex;gap:10px;margin-top:14px;flex-wrap:wrap}
    .btn{padding:10px 14px;border-radius:8px;border:0;cursor:pointer;font-weight:600}
    .btn-primary{background:#0b5ed7;color:#fff}
    .btn-danger{background:#ef4444;color:#fff}
    .btn-outline{background:#fff;border:1px solid #e6e9ef;color:#374151}
    .small{font-size:13px;color:#6b7280}
    .note{font-size:13px;color:#6b7280;margin-top:8px}
  </style>
</head>
<body>
  <div class="card" role="dialog" aria-labelledby="title">
    <h1 id="title">Complete Booking</h1>
    <div class="meta">Reference: <strong><?=htmlspecialchars($ref)?></strong></div>

    <div class="row">
      <div class="box">
        <div class="small">Client Total</div>
        <div style="font-weight:700;font-size:18px">£<?=number_format((float)$clientTotal,2)?></div>
      </div>
      <div class="box">
        <div class="small">Pickup date</div>
        <div style="font-weight:600"><?=htmlspecialchars($pickupDate ?: '—')?></div>
      </div>
      <div class="box">
        <div class="small">Partner commission (info)</div>
        <div style="font-weight:600">£<?=number_format((float)$commission,2)?></div>
      </div>
    </div>

    <hr style="margin:16px 0;border:none;border-top:1px solid #eef2f7">

    <!-- Paid form -->
    <form method="post" style="margin-top:8px" id="paidForm">
      <input type="hidden" name="csrf" value="<?=htmlspecialchars($csrf)?>">
      <input type="hidden" name="id" value="<?= (int)$bid ?>">
      <input type="hidden" name="action" value="paid">

      <label>Amount paid (£)</label>
      <input type="number" name="amount_paid" step="0.01" required id="amountPaid"
             value="<?=htmlspecialchars(number_format((float)$clientTotal,2,'.',''))?>">

      <label style="margin-top:8px">Paid at (date & time)</label>
      <input type="datetime-local" name="paid_at" value="<?=htmlspecialchars(date('Y-m-d\TH:i'))?>">

      <div class="actions">
        <button type="submit" class="btn btn-primary">Mark Paid &amp; Complete</button>
        <button type="button" class="btn btn-outline" onclick="window.close()">Cancel</button>
      </div>
      <div class="note">If you enter less than the Client Total, the remaining balance will be added to Pending Payments.</div>
    </form>

    <!-- Unpaid form -->
    <form method="post" style="margin-top:16px" id="unpaidForm">
      <input type="hidden" name="csrf" value="<?=htmlspecialchars($csrf)?>">
      <input type="hidden" name="id" value="<?= (int)$bid ?>">
      <input type="hidden" name="action" value="unpaid">
      <div class="actions">
        <button type="submit" class="btn btn-danger">Complete Unpaid</button>
        <button type="button" class="btn btn-outline" onclick="window.close()">Cancel</button>
      </div>
      <div class="note">Complete without recording client payment — booking will be recorded as pending payment.</div>
    </form>
  </div>

  <script>
    // Ensure numeric value not empty
    (function(){
      var amtEl = document.getElementById('amountPaid');
      var paidForm = document.getElementById('paidForm');
      paidForm.addEventListener('submit', function(e){
        var v = parseFloat(amtEl.value);
        if (isNaN(v) || v <= 0) {
          e.preventDefault();
          alert('Please enter a positive paid amount.');
          amtEl.focus();
        }
      });
    })();
  </script>
</body>
</html>
