<?php
declare(strict_types=1);

/**
 * modules/accounts/settings/coamap.php
 *
 * Map system posting events → Chart of Accounts codes.
 *
 * Why:
 *  - Controls which COA codes are used when the system auto-posts to the ledger.
 *  - Examples:
 *      booking_income      → CHAUF_INCOME
 *      rental_income       → RENTAL_INCOME
 *      partner_commission  → PARTNER_COMM
 *      driver_payout       → DRIVER_PAYOUT
 *
 * Notes:
 *  - Safe even if the system_coa_map table is temporarily missing: shows a hint.
 *  - Validates account_code belongs to current company COA.
 *  - Upserts per (company_id, event_key).
 */

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

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

$errors = [];
$ok     = null;

/** Helpers */
function table_exists(string $table): bool {
  try {
    $q = db()->query("SHOW TABLES LIKE " . db()->quote($table));
    return (bool)$q->fetchColumn();
  } catch (Throwable $e) { return false; }
}
function coa_exists_for_company(int $cid, string $code): bool {
  $q = db()->prepare("SELECT 1 FROM chart_of_accounts WHERE company_id=:cid AND code=:c LIMIT 1");
  $q->execute([':cid'=>$cid, ':c'=>$code]);
  return (bool)$q->fetchColumn();
}
function load_coa_grouped(int $cid): array {
  $q = db()->prepare("
    SELECT code, name, type, category
    FROM chart_of_accounts
    WHERE company_id = :cid
    ORDER BY FIELD(type,'income','cogs','expense','asset','liability','equity','other'), code ASC
  ");
  $q->execute([':cid'=>$cid]);
  $out = ['income'=>[], 'cogs'=>[], 'expense'=>[], 'asset'=>[], 'liability'=>[], 'equity'=>[], 'other'=>[]];
  while ($r = $q->fetch()) {
    $t = strtolower((string)$r['type']);
    if (!isset($out[$t])) $out[$t] = [];
    $out[$t][] = $r;
  }
  return $out;
}
function load_existing_map(int $cid): array {
  if (!table_exists('system_coa_map')) return [];
  $q = db()->prepare("SELECT event_key, account_code FROM system_coa_map WHERE company_id=:cid");
  $q->execute([':cid'=>$cid]);
  $m = [];
  foreach ($q->fetchAll() as $r) $m[(string)$r['event_key']] = (string)$r['account_code'];
  return $m;
}

/** Known events (add more later if you automate additional postings) */
$EVENTS = [
  // INCOME
  'booking_income' => [
    'label'         => 'Booking Income (Chauffeur jobs)',
    'types'         => ['income'],                  // dropdown limited to these types
    'default_code'  => 'CHAUF_INCOME',
    'help'          => 'Sales from chauffeur bookings & invoices.',
    'section'       => 'Income Mappings',
  ],
  'rental_income' => [
    'label'         => 'Rental Income (Vehicle rentals)',
    'types'         => ['income'],
    'default_code'  => 'RENTAL_INCOME',
    'help'          => 'Sales from rental contracts & invoices.',
    'section'       => 'Income Mappings',
  ],

  // COGS (Cost of Sales) — your P&L places these under COGS
  'partner_commission' => [
    'label'         => 'Partner Commission (COGS)',
    'types'         => ['cogs','expense'],         // allow expense as fallback
    'default_code'  => 'PARTNER_COMM',
    'help'          => 'Commission paid to partners (cost of sales).',
    'section'       => 'COGS Mappings',
  ],
  'driver_payout' => [
    'label'         => 'Driver Payouts (COGS)',
    'types'         => ['cogs','expense'],
    'default_code'  => 'DRIVER_PAYOUT',
    'help'          => 'Payments to self-employed drivers (cost of sales).',
    'section'       => 'COGS Mappings',
  ],
];

/** Load data sets */
$hasMapTable = table_exists('system_coa_map');
$coa         = load_coa_grouped($cid);
$current     = load_existing_map($cid);

/** POST: save mapping */
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  try {
    csrf_verify((string)($_POST['csrf'] ?? ''));
    if (!$hasMapTable) {
      throw new RuntimeException('Mapping table (system_coa_map) is missing.');
    }
    $map = $_POST['map'] ?? [];
    if (!is_array($map)) $map = [];

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

    $ins = $pdo->prepare("
      INSERT INTO system_coa_map (company_id, event_key, account_code, created_at, updated_at)
      VALUES (:cid, :ek, :ac, NOW(), NOW())
      ON DUPLICATE KEY UPDATE account_code=VALUES(account_code), updated_at=NOW()
    ");
    $del = $pdo->prepare("DELETE FROM system_coa_map WHERE company_id=:cid AND event_key=:ek");

    foreach ($EVENTS as $key => $cfg) {
      $val = isset($map[$key]) ? trim((string)$map[$key]) : '';
      if ($val === '') {
        $del->execute([':cid'=>$cid, ':ek'=>$key]);
        continue;
      }
      if (!coa_exists_for_company($cid, $val)) {
        throw new RuntimeException("Invalid COA code for {$cfg['label']}: " . $val);
      }
      $ins->execute([':cid'=>$cid, ':ek'=>$key, ':ac'=>$val]);
    }

    $pdo->commit();
    $current = load_existing_map($cid);
    $ok = 'Mapping saved.';
  } catch (Throwable $e) {
    if (isset($pdo) && $pdo->inTransaction()) $pdo->rollBack();
    $errors[] = (defined('APP_ENV') && APP_ENV === 'dev') ? $e->getMessage() : 'Unable to save mapping.';
  }
}

/** Group events by section for nicer UI */
$sections = [];
foreach ($EVENTS as $k => $cfg) {
  $sec = $cfg['section'] ?? 'Mappings';
  if (!isset($sections[$sec])) $sections[$sec] = [];
  $sections[$sec][$k] = $cfg;
}

/** Render */
include dirname(__DIR__, 3) . '/includes/header.php';
?>
<div class="d-flex justify-content-between align-items-center mb-3">
  <div>
    <h1 class="h4 mb-0">COA Mapping</h1>
    <div class="text-muted">Choose which account codes the system uses for automatic postings.</div>
  </div>
  <div class="d-flex gap-2">
    <a class="btn btn-outline-secondary" href="<?= e(url_modules('accounts/index.php')) ?>">← Accounts Dashboard</a>
  </div>
</div>

<?php if (!$hasMapTable): ?>
  <div class="alert alert-warning">
    <div class="fw-semibold mb-1">Heads up: <code>system_coa_map</code> table not found.</div>
    <div class="small">
      Create it (if you haven’t already):
      <pre class="mb-0 small">
CREATE TABLE IF NOT EXISTS system_coa_map (
  id           INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  company_id   INT UNSIGNED NOT NULL,
  event_key    VARCHAR(64)  NOT NULL,
  account_code VARCHAR(32)  NOT NULL,
  created_at   DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at   DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_company_event (company_id, event_key),
  KEY idx_company_code (company_id, account_code),
  CONSTRAINT fk_map_company  FOREIGN KEY (company_id)   REFERENCES companies(id) ON DELETE CASCADE ON UPDATE CASCADE
  -- (Optional) add FK to chart_of_accounts if you use a composite key
);
      </pre>
    </div>
  </div>
<?php endif; ?>

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

<form method="post" class="card shadow-sm">
  <input type="hidden" name="csrf" value="<?= e(csrf_token()) ?>">
  <div class="card-body">
    <?php foreach ($sections as $title => $items): ?>
      <h2 class="h6 text-uppercase text-muted mt-2 mb-2"><?= e($title) ?></h2>
      <div class="table-responsive">
        <table class="table align-middle">
          <thead class="table-light">
            <tr>
              <th style="width:35%;">Event</th>
              <th style="width:45%;">Account Code</th>
              <th>Help</th>
            </tr>
          </thead>
          <tbody>
            <?php foreach ($items as $key => $cfg):
              $selected = $current[$key] ?? '';
              // If nothing saved yet, try to preselect default if it exists in COA.
              if ($selected === '' && !empty($cfg['default_code']) && coa_exists_for_company($cid, $cfg['default_code'])) {
                $selected = $cfg['default_code'];
              }
              $allowedTypes = $cfg['types'] ?? ['income','expense','cogs','other'];
              // Build the options list for the allowed types (with subtle group headers)
            ?>
              <tr>
                <td>
                  <div class="fw-semibold"><?= e($cfg['label']) ?></div>
                  <div class="text-muted small"><code><?= e($key) ?></code></div>
                </td>
                <td>
                  <select name="map[<?= e($key) ?>]" class="form-select">
                    <option value="">— Not set —</option>
                    <?php foreach ($allowedTypes as $t): if (!empty($coa[$t])): ?>
                      <optgroup label="<?= e(ucfirst($t)) ?>">
                        <?php foreach ($coa[$t] as $acc): ?>
                          <?php $val = (string)$acc['code']; ?>
                          <option value="<?= e($val) ?>" <?= $val === $selected ? 'selected' : '' ?>>
                            <?= e($acc['code']) ?> — <?= e($acc['name']) ?>
                          </option>
                        <?php endforeach; ?>
                      </optgroup>
                    <?php endif; endforeach; ?>

                    <?php
                    // Fallback group if none of the allowed types has items
                    $hasAny = false;
                    foreach ($allowedTypes as $t) if (!empty($coa[$t])) { $hasAny = true; break; }
                    if (!$hasAny):
                    ?>
                      <optgroup label="All Accounts">
                        <?php foreach ($coa as $tt => $list): foreach ($list as $acc): ?>
                          <?php $val = (string)$acc['code']; ?>
                          <option value="<?= e($val) ?>" <?= $val === $selected ? 'selected' : '' ?>>
                            [<?= e(ucfirst($tt)) ?>] <?= e($acc['code']) ?> — <?= e($acc['name']) ?>
                          </option>
                        <?php endforeach; endforeach; ?>
                      </optgroup>
                    <?php endif; ?>
                  </select>
                  <?php if (!empty($cfg['default_code'])): ?>
                    <div class="small text-muted mt-1">Suggested default: <code><?= e($cfg['default_code']) ?></code></div>
                  <?php endif; ?>
                </td>
                <td class="text-muted small"><?= e($cfg['help'] ?? '') ?></td>
              </tr>
            <?php endforeach; ?>
          </tbody>
        </table>
      </div>
      <hr class="my-3">
    <?php endforeach; ?>
    <div class="d-flex gap-2">
      <button class="btn btn-dark">Save Mapping</button>
      <a class="btn btn-outline-secondary" href="<?= e(url_modules('accounts/index.php')) ?>">Cancel</a>
    </div>
  </div>
</form>

<div class="card shadow-sm mt-3">
  <div class="card-body small text-muted">
    <div class="fw-semibold mb-1">How this is used</div>
    <ul class="mb-0">
      <li><strong>Booking completed / invoiced</strong>: posts to the code set for <code>booking_income</code>.</li>
      <li><strong>Rental invoiced</strong>: posts to the code set for <code>rental_income</code>.</li>
      <li><strong>Partner commission</strong>: expense to <code>partner_commission</code> (COGS).</li>
      <li><strong>Driver payouts</strong>: expense to <code>driver_payout</code> (COGS).</li>
    </ul>
  </div>
</div>

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