<?php
declare(strict_types=1);

/**
 * modules/payments/mark_paid.php
 *
 * Driver payout posting with guaranteed accounting + pending balance.
 *
 * - Always inserts into driver_payouts
 * - Always inserts into transactions (DRIVER_PAYOUT, Chauffeur, expense)
 * - If cumulative paid < driver_due => upsert (delete+insert) into pending_payments (type='driver')
 * - If fully paid => ensure no pending row remains for type='driver'
 *
 * Notes:
 * - Creates pending_payments table if missing (best-effort) to avoid silent skips.
 * - Throws explicit errors if transactions insert fails.
 */

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

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

$errors = [];
$notice = null;

$bookingId = (int)($_GET['booking_id'] ?? $_POST['booking_id'] ?? 0);
$driverId  = (int)($_GET['driver_id']  ?? $_POST['driver_id']  ?? 0);
$returnUrl = (string)($_GET['return']   ?? $_POST['return']     ?? url_modules('payments/drivers.php'));

if ($bookingId <= 0) redirect($returnUrl);

/** helpers */
function table_exists(string $t): bool {
  try { db()->query("SELECT 1 FROM `{$t}` LIMIT 1"); return true; } catch(Throwable $e){ return false; }
}
function sum_driver_paid(int $cid, int $bid): float {
  try {
    $q = db()->prepare("SELECT COALESCE(SUM(amount),0) FROM driver_payouts WHERE company_id=:c AND booking_id=:b");
    $q->execute([':c'=>$cid, ':b'=>$bid]); return (float)$q->fetchColumn();
  } catch(Throwable $e){ return 0.0; }
}
function resolve_primary_driver(int $bid): ?int {
  try {
    $q = db()->prepare("SELECT driver_id FROM booking_vehicles WHERE booking_id=:b ORDER BY sequence_order ASC, id ASC LIMIT 1");
    $q->execute([':b'=>$bid]); $v = $q->fetchColumn();
    return $v ? (int)$v : null;
  } catch(Throwable $e){ return null; }
}
function decode_bank(?string $json): array {
  $d=['bank_name'=>'','account_name'=>'','account_number'=>'','sort_code'=>'','iban'=>'','notes'=>''];
  if(!$json) return $d; $arr=json_decode($json,true);
  return is_array($arr)? array_merge($d, array_intersect_key($arr,$d)) : $d;
}

/** load booking */
$bq = db()->prepare("
  SELECT b.*,
         (COALESCE(b.total_driver_price,0) + COALESCE(b.driver_parking_fee,0) + COALESCE(b.driver_waiting_fee,0)) AS driver_due
  FROM bookings b
  WHERE b.id=:id AND b.company_id=:cid
  LIMIT 1
");
$bq->execute([':id'=>$bookingId, ':cid'=>$cid]);
$booking = $bq->fetch();
if(!$booking){ $errors[]='Booking not found.'; }

if ($driverId <= 0) {
  $resolved = resolve_primary_driver($bookingId);
  if ($resolved) $driverId = $resolved;
}

$driver=null; $bank=null;
if ($driverId > 0) {
  $dq = db()->prepare("SELECT id,name,phone,bank_details FROM drivers WHERE id=:id AND company_id=:cid LIMIT 1");
  $dq->execute([':id'=>$driverId, ':cid'=>$cid]);
  $driver = $dq->fetch() ?: null;
  $bank   = decode_bank($driver['bank_details'] ?? null);
} else {
  $errors[]='No driver assigned.';
}

$driverDue     = (float)($booking['driver_due'] ?? 0.0);
$alreadyPaid   = sum_driver_paid($cid, $bookingId);
$outstanding   = max(0.0, round($driverDue - $alreadyPaid, 2));
$bookingRef    = (string)($booking['booking_ref'] ?? ('#'.$bookingId));

/** ensure pending_payments exists (best-effort; matches your semantics) */
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(10) UNSIGNED NOT NULL,
        booking_id BIGINT(20) 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,
        created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        status VARCHAR(32) NOT NULL DEFAULT 'pending',
        KEY idx_company_booking (company_id, booking_id),
        KEY idx_type (type)
      ) ENGINE=MyISAM DEFAULT CHARSET=latin1
    ");
  } catch (Throwable $e) {
    // ignore; insert will gracefully no-op if table truly absent
  }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'mark_paid') {
  try {
    csrf_verify((string)($_POST['csrf'] ?? ''));

    $amt    = (float)($_POST['amount'] ?? 0);
    $paidAt = (string)($_POST['paid_at'] ?? '');
    $method = trim((string)($_POST['method'] ?? 'Bank Transfer'));
    $ref    = trim((string)($_POST['reference'] ?? ''));
    $notes  = trim((string)($_POST['notes'] ?? ''));

    if ($amt <= 0) throw new RuntimeException('Amount must be positive.');
    if ($outstanding <= 0) throw new RuntimeException('Nothing outstanding for this booking.');
    if ($amt > $outstanding) throw new RuntimeException('Amount cannot exceed outstanding (£'.number_format($outstanding,2).').');
    if ($paidAt === '') $paidAt = date('Y-m-d H:i:s');

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

    // 1) driver_payouts
    $p = $pdo->prepare("
      INSERT INTO driver_payouts
        (company_id, booking_id, driver_id, amount, paid_at, method, reference, notes, created_at)
      VALUES
        (:c,:b,:d,:a,:t,:m,:r,:n,NOW())
    ");
    $p->execute([
      ':c'=>$cid, ':b'=>$bookingId, ':d'=>$driverId, ':a'=>$amt,
      ':t'=>$paidAt,
      ':m'=>$method !== '' ? $method : null,
      ':r'=>$ref !== '' ? $ref : null,
      ':n'=>$notes !== '' ? $notes : null,
    ]);

    // 2) transactions (must ALWAYS happen)
    if (!table_exists('transactions')) {
      throw new RuntimeException('Transactions table missing.');
    }
    $tx = $pdo->prepare("
      INSERT INTO transactions
        (company_id, date, account_code, segment, type, amount, booking_id, reference, notes, created_at)
      VALUES
        (:c, DATE(:t), 'DRIVER_PAYOUT', 'Chauffeur', 'expense', :a, :b, :r, :n, NOW())
    ");
    $tx->execute([
      ':c'=>$cid,
      ':t'=>$paidAt,
      ':a'=>$amt,
      ':b'=>$bookingId,
      ':r'=> $ref !== '' ? $ref : ('Driver payout for '.$bookingRef),
      ':n'=> $notes !== '' ? $notes : null,
    ]);
    if ($tx->rowCount() !== 1) {
      throw new RuntimeException('Accounting entry not recorded.');
    }

    // 3) pending_payments (type='driver') — keep only if balance remains
    $newPaidTotal = round($alreadyPaid + $amt, 2);
    $newBalance   = max(0.0, round($driverDue - $newPaidTotal, 2));

    if (table_exists('pending_payments')) {
      // remove previous 'driver' pending rows only for this booking
      $del = $pdo->prepare("DELETE FROM pending_payments WHERE company_id=:c AND booking_id=:b AND type='driver'");
      $del->execute([':c'=>$cid, ':b'=>$bookingId]);

      if ($newBalance > 0) {
        $insPend = $pdo->prepare("
          INSERT INTO pending_payments
            (company_id, booking_id, booking_ref, `type`, total_due, amount_paid, balance_due, status, created_at)
          VALUES
            (:c,:b,:ref,'driver',:total,:paid,:bal,'pending',NOW())
        ");
        $insPend->execute([
          ':c'=>$cid,
          ':b'=>$bookingId,
          ':ref'=>$bookingRef,
          ':total'=> round($driverDue,2),
          ':paid' => $newPaidTotal,
          ':bal'  => $newBalance,
        ]);
      }
    }

    audit_log('payout.driver.create', 'booking', $bookingId, [
      'driver_id'          => $driverId,
      'amount'             => $amt,
      'paid_at'            => $paidAt,
      'method'             => $method,
      'reference'          => $ref,
      'total_due'          => round($driverDue,2),
      'paid_after'         => $newPaidTotal,
      'balance_remaining'  => $newBalance,
    ]);

    $pdo->commit();
    $redir = $returnUrl . (str_contains($returnUrl,'?') ? '&' : '?') . 'ok=1';
    redirect($redir);

  } catch (Throwable $e) {
    if (isset($pdo) && $pdo->inTransaction()) $pdo->rollBack();
    $errors[] = (defined('APP_ENV') && APP_ENV === 'dev') ? $e->getMessage() : 'Unable to save payout.';
  }
}

/** render */
include dirname(__DIR__, 2) . '/includes/header.php';
?>
<div class="d-flex justify-content-between align-items-center mb-3">
  <h1 class="h4 mb-0">Mark Driver Payout</h1>
  <div class="d-flex gap-2">
    <a href="<?= e($returnUrl) ?>" class="btn btn-outline-secondary">Back</a>
  </div>
</div>

<?php if ($notice): ?><div class="alert alert-success"><?= e($notice) ?></div><?php endif; ?>
<?php if ($errors): ?>
  <div class="alert alert-danger"><ul class="mb-0"><?php foreach ($errors as $er) echo '<li>'.e($er).'</li>'; ?></ul></div>
<?php endif; ?>

<?php if ($booking): ?>
<div class="row g-3">
  <div class="col-12 col-xl-7">
    <div class="card shadow-sm h-100">
      <div class="card-body">
        <h2 class="h6 text-uppercase text-muted mb-3">Booking</h2>
        <div class="row g-3">
          <div class="col-md-4"><div class="small text-muted">Reference</div><div class="fw-semibold"><?= e($bookingRef) ?></div></div>
          <div class="col-md-4"><div class="small text-muted">Client</div><div class="fw-semibold"><?= e($booking['client_name'] ?? '—') ?></div></div>
          <div class="col-md-4"><div class="small text-muted">Pickup</div><div class="fw-semibold"><?= e(trim(($booking['pickup_date'] ?? '').' '.($booking['pickup_time'] ?? ''))) ?></div></div>
        </div>

        <hr>
        <h2 class="h6 text-uppercase text-muted mb-3">Driver</h2>
        <div class="row g-3">
          <div class="col-md-6"><div class="small text-muted">Name</div><div class="fw-semibold"><?= $driver ? e($driver['name']) : '<span class="text-muted">No driver</span>' ?></div></div>
          <div class="col-md-6"><div class="small text-muted">Phone</div><div class="fw-semibold"><?= e($driver['phone'] ?? '—') ?></div></div>
        </div>

        <hr>
        <h2 class="h6 text-uppercase text-muted mb-3">Amounts</h2>
        <div class="row g-3">
          <div class="col-md-4"><div class="p-2 border rounded bg-light"><div class="small text-muted">Driver Due</div><div class="fw-bold">£<?= number_format($driverDue,2) ?></div></div></div>
          <div class="col-md-4"><div class="p-2 border rounded bg-light"><div class="small text-muted">Paid So Far</div><div class="fw-bold">£<?= number_format($alreadyPaid,2) ?></div></div></div>
          <div class="col-md-4"><div class="p-2 border rounded bg-light"><div class="small text-muted">Outstanding</div><div class="fw-bold">£<?= number_format($outstanding,2) ?></div></div></div>
        </div>

        <hr>
        <h2 class="h6 text-uppercase text-muted mb-3">Record Payout</h2>
        <form method="post" class="row g-3">
          <input type="hidden" name="csrf" value="<?= e(csrf_token()) ?>">
          <input type="hidden" name="action" value="mark_paid">
          <input type="hidden" name="booking_id" value="<?= (int)$bookingId ?>">
          <input type="hidden" name="driver_id" value="<?= (int)$driverId ?>">
          <input type="hidden" name="return" value="<?= e($returnUrl) ?>">

          <div class="col-md-4">
            <label class="form-label">Amount (£)</label>
            <input type="number" class="form-control" step="0.01" min="0.01"
                   max="<?= e(number_format($outstanding,2,'.','')) ?>"
                   required name="amount"
                   value="<?= e(number_format($outstanding > 0 ? $outstanding : 0,2,'.','')) ?>">
          </div>
          <div class="col-md-4">
            <label class="form-label">Paid At</label>
            <input type="datetime-local" class="form-control" name="paid_at" value="<?= e(date('Y-m-d\TH:i')) ?>">
          </div>
          <div class="col-md-4">
            <label class="form-label">Method</label>
            <input class="form-control" name="method" value="Bank Transfer" placeholder="Bank Transfer / Cash / Card">
          </div>
          <div class="col-md-6">
            <label class="form-label">Reference</label>
            <input class="form-control" name="reference" placeholder="Txn ID / internal note">
          </div>
          <div class="col-md-6">
            <label class="form-label">Notes (optional)</label>
            <input class="form-control" name="notes" placeholder="Any additional info">
          </div>
          <div class="col-12 d-flex gap-2">
            <button class="btn btn-dark">Save Payout</button>
            <a class="btn btn-outline-secondary" href="<?= e($returnUrl) ?>">Cancel</a>
          </div>
        </form>
      </div>
    </div>
  </div>

  <div class="col-12 col-xl-5">
    <div class="card shadow-sm h-100">
      <div class="card-body">
        <h2 class="h6 text-uppercase text-muted mb-3">Driver Bank Details</h2>
        <?php if ($driver): $b=$bank; ?>
          <table class="table table-sm mb-0"><tbody>
            <tr><th>Bank</th><td><?= e($b['bank_name'] ?: '—') ?></td></tr>
            <tr><th>Account Holder</th><td><?= e($b['account_name'] ?: '—') ?></td></tr>
            <tr><th>Account Number</th><td><?= e($b['account_number'] ?: '—') ?></td></tr>
            <tr><th>Sort Code</th><td><?= e($b['sort_code'] ?: '—') ?></td></tr>
            <tr><th>IBAN</th><td><?= e($b['iban'] ?: '—') ?></td></tr>
            <tr><th>Notes</th><td><?= nl2br(e($b['notes'] ?: '—')) ?></td></tr>
          </tbody></table>
          <div class="small text-muted mt-2">Verify details before payment.</div>
        <?php else: ?>
          <div class="text-muted">No driver selected.</div>
        <?php endif; ?>
      </div>
    </div>
  </div>
</div>
<?php endif; ?>

<?php include dirname(__DIR__, 2) . '/includes/footer.php'; ?>
