<?php
require_once __DIR__ . '/../app/config/config.php';
require_once __DIR__ . '/../app/middleware/auth.php';

require_once __DIR__ . '/../app/models/LaundryBag.php';
require_once __DIR__ . '/../app/models/LaundryBagEvent.php';
require_once __DIR__ . '/../app/models/LaundryItemType.php';

$hasAudit = file_exists(__DIR__ . '/../app/models/AuditLog.php');
if ($hasAudit) require_once __DIR__ . '/../app/models/AuditLog.php';

require_login();
$user = current_user();
$userId = isset($user['id']) ? (int)$user['id'] : null;

$bagId = (int)($_GET['bag_id'] ?? 0);
if (!$bagId) exit('Invalid bag.');

$bag = LaundryBag::getWithUnit($bagId);
if (!$bag) exit('Bag not found.');

$itemTypesRows = LaundryItemType::allActive();
$itemTypes = [];
foreach ($itemTypesRows as $r) $itemTypes[(string)$r['code']] = (string)$r['name'];

$statuses = [
  'picked_up'  => 'Picked Up',
  'delivered'  => 'Delivered',
  'clean'      => 'Clean',
  'dirty'      => 'Dirty',
];

function logAuditIfAvailable(bool $hasAudit, ?int $userId, array $payload): void {
  if ($hasAudit && class_exists('AuditLog')) {
    AuditLog::log($userId, 'LAUNDRY_TRANSACTION', $payload);
  }
}

function getCurrentStatus(int $bagId, string $itemType): string {
  $items = LaundryBag::items($bagId);
  foreach ($items as $r) {
    if (($r['item_type'] ?? '') === $itemType) {
      return (string)($r['status'] ?? 'dirty');
    }
  }
  return 'dirty';
}

function ensureItemExists(int $bagId, string $itemType): void {
  $items = LaundryBag::items($bagId);
  foreach ($items as $r) {
    if (($r['item_type'] ?? '') === $itemType) return;
  }
  LaundryBag::upsertItem($bagId, $itemType, 'dirty');
}

$ok = null;
$error = null;

$bagItemsByType = [];
$items = LaundryBag::items($bagId);
foreach ($items as $it) $bagItemsByType[$it['item_type']] = $it;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  try {
    $geoLat = isset($_POST['geo_lat']) && $_POST['geo_lat'] !== '' ? (float)$_POST['geo_lat'] : null;
    $geoLng = isset($_POST['geo_lng']) && $_POST['geo_lng'] !== '' ? (float)$_POST['geo_lng'] : null;
    $geoAcc = isset($_POST['geo_accuracy']) && $_POST['geo_accuracy'] !== '' ? (int)$_POST['geo_accuracy'] : null;

    $geoAddress = trim($_POST['geo_address'] ?? '');
    $geoAddress = $geoAddress !== '' ? $geoAddress : null;

    // Quick action: qa = "item|action"
    if (!empty($_POST['qa'])) {
      $qa = (string)$_POST['qa'];
      $parts = explode('|', $qa, 2);
      if (count($parts) !== 2) throw new Exception("Invalid quick action.");

      [$itemType, $action] = $parts;
      $itemType = strtolower(trim($itemType));
      $action = strtolower(trim($action));

      if (!isset($itemTypes[$itemType])) throw new Exception("Invalid item type.");

      ensureItemExists($bagId, $itemType);
      $oldStatus = getCurrentStatus($bagId, $itemType);
      $statusAfter = $oldStatus;

      if ($action === 'picked_up') {
        LaundryBag::upsertItem($bagId, $itemType, 'picked_up');
        $statusAfter = 'picked_up';
      } elseif ($action === 'cleaning') {
        $statusAfter = $oldStatus;
      } elseif ($action === 'delivered') {
        LaundryBag::upsertItem($bagId, $itemType, 'delivered');
        $statusAfter = 'delivered';
      } elseif ($action === 'marked_clean') {
        LaundryBag::upsertItem($bagId, $itemType, 'clean');
        $statusAfter = 'clean';
      } elseif ($action === 'marked_dirty') {
        LaundryBag::upsertItem($bagId, $itemType, 'dirty');
        $statusAfter = 'dirty';
      } else {
        throw new Exception("Unknown action.");
      }

      LaundryBagEvent::add(
        $bagId,
        $itemType,
        $action,
        $statusAfter,
        $userId,
        null,
        $geoLat,
        $geoLng,
        $geoAcc,
        $geoAddress
      );

      logAuditIfAvailable($hasAudit, $userId, [
        'bag_id' => $bagId,
        'bag_number' => $bag['bag_number'],
        'unit_id' => (int)$bag['unit_id'],
        'item_type' => $itemType,
        'action' => $action,
        'from' => $oldStatus,
        'to' => $statusAfter,
        'geo_lat' => $geoLat,
        'geo_lng' => $geoLng,
        'geo_accuracy' => $geoAcc,
        'geo_address' => $geoAddress,
      ]);

      $ok = "Transaction saved.";
    }

    // Full save (bag number + included items/statuses)
    if (isset($_POST['save_bag'])) {
      $bagNumber = trim($_POST['bag_number'] ?? '');
      if ($bagNumber === '') throw new Exception("Bag number is required.");

      LaundryBag::createOrUpdateBag((int)$bag['unit_id'], $bagNumber);

      $current = [];
      foreach (LaundryBag::items($bagId) as $r) $current[$r['item_type']] = $r;

      foreach ($itemTypes as $code => $label) {
        $enabled = isset($_POST['has_' . $code]);
        if (!$enabled) continue;

        $newStatus = strtolower(trim($_POST['status_' . $code] ?? 'dirty'));
        if (!isset($statuses[$newStatus])) $newStatus = 'dirty';

        $oldStatus = strtolower($current[$code]['status'] ?? '');
        LaundryBag::upsertItem($bagId, $code, $newStatus);

        if ($oldStatus !== $newStatus) {
          $action = match($newStatus) {
            'picked_up' => 'picked_up',
            'delivered' => 'delivered',
            'clean' => 'marked_clean',
            'dirty' => 'marked_dirty',
            default => 'marked_dirty',
          };

          LaundryBagEvent::add(
            $bagId,
            $code,
            $action,
            $newStatus,
            $userId,
            null,
            $geoLat,
            $geoLng,
            $geoAcc,
            $geoAddress
          );

          logAuditIfAvailable($hasAudit, $userId, [
            'bag_id' => $bagId,
            'bag_number' => $bagNumber,
            'unit_id' => (int)$bag['unit_id'],
            'item_type' => $code,
            'action' => $action,
            'from' => $oldStatus ?: null,
            'to' => $newStatus,
            'geo_lat' => $geoLat,
            'geo_lng' => $geoLng,
            'geo_accuracy' => $geoAcc,
            'geo_address' => $geoAddress,
          ]);
        }
      }

      $ok = "Bag saved.";
    }

    $bag = LaundryBag::getWithUnit($bagId);
    $bagItemsByType = [];
    $items = LaundryBag::items($bagId);
    foreach ($items as $it) $bagItemsByType[$it['item_type']] = $it;

  } catch (Throwable $e) {
    $error = $e->getMessage();
  }
}

$pageTitle = 'Manage Laundry Bag';
require_once __DIR__ . '/../app/views/partials/header.php';
?>

<div class="container">

  <div class="card p-4 mb-3">
    <div class="d-flex justify-content-between flex-wrap gap-2">
      <div>
        <h5 class="page-title mb-1">Manage Laundry Bag</h5>
        <div class="text-muted">
          <?= htmlspecialchars($bag['building_name']) ?> • Unit
          <a href="<?= BASE_URL ?>/unit.php?id=<?= (int)$bag['unit_id'] ?>"><?= htmlspecialchars($bag['unit_code']) ?></a>
          <div class="small mt-1">Bag #: <strong><?= htmlspecialchars($bag['bag_number']) ?></strong></div>

          <div class="small mt-1 text-muted">
            <div id="geoStatus">Getting location…</div>
            <div id="geoAddr" class="small"></div>
          </div>
        </div>
      </div>
      <div class="d-flex gap-2 flex-wrap">
        <a class="btn btn-outline-primary" href="<?= BASE_URL ?>/laundry.php">Laundry Dashboard</a>
        <a class="btn btn-outline-secondary" href="<?= BASE_URL ?>/laundry_worklist.php">Worklist</a>
        <a class="btn btn-outline-secondary" href="<?= BASE_URL ?>/laundry_transactions.php?bag_id=<?= (int)$bagId ?>">Transactions</a>
        <a class="btn btn-outline-secondary" href="<?= BASE_URL ?>/laundry_items.php">Bag Items (CRUD)</a>
      </div>
    </div>
  </div>

  <?php if ($ok): ?><div class="alert alert-success"><?= htmlspecialchars($ok) ?></div><?php endif; ?>
  <?php if ($error): ?><div class="alert alert-danger"><?= htmlspecialchars($error) ?></div><?php endif; ?>

  <div class="card p-4">
    <form id="laundryForm" method="post">

      <!-- hidden geo fields -->
      <input type="hidden" name="geo_lat" id="geo_lat">
      <input type="hidden" name="geo_lng" id="geo_lng">
      <input type="hidden" name="geo_accuracy" id="geo_accuracy">
      <input type="hidden" name="geo_address" id="geo_address">

      <label class="form-label">Bag Number</label>
      <input class="form-control" name="bag_number" value="<?= htmlspecialchars($bag['bag_number'] ?? '') ?>" required>

      <hr class="my-4">

      <h6 class="mb-2">Items inside this bag</h6>

      <div class="row g-3">
        <?php foreach ($itemTypes as $code => $label): ?>
          <?php
            $row = $bagItemsByType[$code] ?? null;
            $checked = $row ? true : false;
            $status = $row['status'] ?? 'dirty';
          ?>
          <div class="col-md-6">
            <div class="border rounded p-3">
              <div class="d-flex justify-content-between align-items-center mb-2">
                <div class="form-check">
                  <input class="form-check-input" type="checkbox" id="has_<?= htmlspecialchars($code) ?>" name="has_<?= htmlspecialchars($code) ?>" <?= $checked ? 'checked' : '' ?>>
                  <label class="form-check-label fw-semibold" for="has_<?= htmlspecialchars($code) ?>">
                    <?= htmlspecialchars($label) ?>
                  </label>
                </div>
                <?php if ($checked): ?>
                  <span class="badge badge-soft"><?= htmlspecialchars(ucwords(str_replace('_',' ', $status))) ?></span>
                <?php endif; ?>
              </div>

              <label class="form-label small">Status</label>
              <select class="form-select" name="status_<?= htmlspecialchars($code) ?>">
                <?php foreach ($statuses as $val => $text): ?>
                  <option value="<?= htmlspecialchars($val) ?>" <?= $val === $status ? 'selected' : '' ?>>
                    <?= htmlspecialchars($text) ?>
                  </option>
                <?php endforeach; ?>
              </select>

              <?php if ($checked): ?>
                <div class="d-flex gap-2 flex-wrap mt-3">
                  <button class="btn btn-sm btn-outline-warning" name="qa" value="<?= htmlspecialchars($code) ?>|picked_up">Picked Up</button>
                  <button class="btn btn-sm btn-outline-secondary" name="qa" value="<?= htmlspecialchars($code) ?>|cleaning">Cleaning</button>
                  <button class="btn btn-sm btn-outline-primary" name="qa" value="<?= htmlspecialchars($code) ?>|delivered">Delivered</button>
                  <button class="btn btn-sm btn-outline-success" name="qa" value="<?= htmlspecialchars($code) ?>|marked_clean">Mark Clean</button>
                  <button class="btn btn-sm btn-outline-danger" name="qa" value="<?= htmlspecialchars($code) ?>|marked_dirty">Mark Dirty</button>
                </div>
              <?php else: ?>
                <div class="text-muted small mt-2">Check this item to enable quick actions.</div>
              <?php endif; ?>

              <?php if ($row && !empty($row['updated_at'])): ?>
                <div class="text-muted small mt-2">Updated: <?= htmlspecialchars($row['updated_at']) ?></div>
              <?php endif; ?>
            </div>
          </div>
        <?php endforeach; ?>
      </div>

      <button class="btn btn-primary w-100 mt-4" name="save_bag" value="1">Save Bag</button>

      <div class="form-text mt-2">
        If location permission is denied, the transaction will still save but without address.
      </div>

    </form>
  </div>

</div>

<script>
(function() {
  const statusEl = document.getElementById('geoStatus');
  const addrEl = document.getElementById('geoAddr');

  const latEl = document.getElementById('geo_lat');
  const lngEl = document.getElementById('geo_lng');
  const accEl = document.getElementById('geo_accuracy');
  const addressEl = document.getElementById('geo_address');

  const form = document.getElementById('laundryForm');

  let inFlight = false;
  let hasGeo = false;

  function setStatus(msg) { if (statusEl) statusEl.textContent = msg; }
  function setAddr(msg) { if (addrEl) addrEl.textContent = msg; }

  async function reverseGeocode(lat, lng) {
    try {
      const url = `<?= BASE_URL ?>/geo_reverse.php?lat=${encodeURIComponent(lat)}&lng=${encodeURIComponent(lng)}`;
      const res = await fetch(url, { credentials: 'same-origin' });
      const json = await res.json();
      if (json && json.ok && json.address) return String(json.address);
    } catch (e) {}
    return '';
  }

  async function getGeoAndAddress() {
    if (inFlight) return;
    inFlight = true;

    try {
      if (!navigator.geolocation) {
        setStatus('Location not supported.');
        setAddr('');
        inFlight = false;
        return;
      }

      setStatus('Getting location…');
      setAddr('');

      const pos = await new Promise((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(resolve, reject, {
          enableHighAccuracy: true,
          timeout: 10000,
          maximumAge: 0
        });
      });

      const c = pos.coords || {};
      latEl.value = c.latitude ?? '';
      lngEl.value = c.longitude ?? '';
      accEl.value = c.accuracy ? Math.round(c.accuracy) : '';

      hasGeo = !!(latEl.value && lngEl.value);
      if (!hasGeo) {
        setStatus('Location not available.');
        setAddr('');
        inFlight = false;
        return;
      }

      setStatus(`Location saved (±${accEl.value || '?'}m). Getting address…`);
      const addr = await reverseGeocode(latEl.value, lngEl.value);

      if (addr) {
        addressEl.value = addr;
        setStatus(`Location saved (±${accEl.value || '?'}m).`);
        setAddr(addr);
      } else {
        addressEl.value = '';
        setStatus(`Location saved (±${accEl.value || '?'}m). Address not available.`);
        setAddr('');
      }

    } catch (err) {
      setStatus('Location not available (permission denied or timeout).');
      setAddr('');
      hasGeo = false;
      addressEl.value = '';
    } finally {
      inFlight = false;
    }
  }

  // Load
  getGeoAndAddress();

  // Ensure geo attempt before submit if empty (we still submit even if address fails)
  form?.addEventListener('submit', async function(e) {
    const hasLatLng = !!(latEl.value && lngEl.value);
    if (hasLatLng) return;

    e.preventDefault();
    await getGeoAndAddress();
    form.submit();
  });
})();
</script>

<?php require_once __DIR__ . '/../app/views/partials/footer.php'; ?>
