<?php
require_once __DIR__ . '/config.php';

header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');

$action = $_REQUEST['action'] ?? '';

try {
  switch ($action) {
    case 'complete_habit':
      requirePost();
      completeHabit();
      break;

    case 'complete_bounty':
      requirePost();
      completeBounty();
      break;

    case 'get_item':
      requireGet();
      getItem();
      break;

    case 'get_day_details':
      requireGet();
      getDayDetails();
      break;

    default:
      respond(['success' => false, 'message' => 'Unknown action']);
  }
} catch (Throwable $e) {
  respond(['success' => false, 'message' => 'Server error']);
}

/* ---------------- Helpers ---------------- */

function respond(array $payload): void {
  echo json_encode($payload);
  exit;
}

function requirePost(): void {
  if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    respond(['success' => false, 'message' => 'Method not allowed']);
  }
}

function requireGet(): void {
  if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'GET') {
    respond(['success' => false, 'message' => 'Method not allowed']);
  }
}

function validDateYmd(string $date): bool {
  $dt = DateTime::createFromFormat('Y-m-d', $date);
  return $dt && $dt->format('Y-m-d') === $date;
}

/* ---------------- Actions ---------------- */

function completeHabit(): void {
  $habitId = (int)($_POST['habit_id'] ?? 0);
  if ($habitId <= 0) respond(['success' => false, 'message' => 'Invalid habit ID']);

  $db = getDB();
  $dayOfWeek = (int)date('w');

  $warnings = [];
  $consumed = [];

  try {
    $db->beginTransaction();

    // Prevent duplicate completion today
    $stmt = $db->prepare("SELECT id FROM completions WHERE habit_id = ? AND completed_date = CURDATE() LIMIT 1");
    $stmt->execute([$habitId]);
    if ($stmt->fetch()) {
      $db->rollBack();
      respond(['success' => false, 'message' => 'Already completed today']);
    }

    // Champion for today
    $stmt = $db->prepare("SELECT id FROM champions WHERE day_index = ? LIMIT 1");
    $stmt->execute([$dayOfWeek]);
    $champion = $stmt->fetch();
    if (!$champion) {
      $db->rollBack();
      respond(['success' => false, 'message' => 'Champion not found']);
    }

    // Habit XP
    $stmt = $db->prepare("SELECT xp_reward FROM habits WHERE id = ? LIMIT 1");
    $stmt->execute([$habitId]);
    $habit = $stmt->fetch();
    if (!$habit) {
      $db->rollBack();
      respond(['success' => false, 'message' => 'Habit not found']);
    }

    // PARTIAL DEDUCTION MODE
    $stmt = $db->prepare("
      SELECT hic.item_id, hic.qty AS needed_qty, i.name, i.quantity AS have_qty
      FROM habit_item_costs hic
      JOIN items i ON i.id = hic.item_id
      WHERE hic.habit_id = ?
      FOR UPDATE
    ");
    $stmt->execute([$habitId]);
    $costs = $stmt->fetchAll();

    if (count($costs) > 0) {
      $upd = $db->prepare("UPDATE items SET quantity = quantity - ? WHERE id = ?");

      foreach ($costs as $c) {
        $itemId = (int)$c['item_id'];
        $need   = (int)$c['needed_qty'];
        $have   = (int)$c['have_qty'];
        $name   = (string)$c['name'];

        if ($need <= 0) continue;

        $use = min($have, $need);
        if ($use > 0) {
          $upd->execute([$use, $itemId]);
          $consumed[] = [
            'item_id' => $itemId,
            'name'    => $name,
            'qty'     => $use
          ];
        }

        if ($use < $need) {
          $warnings[] = [
            'item_id' => $itemId,
            'name'    => $name,
            'needed'  => $need,
            'have'    => $have,
            'used'    => $use,
            'short'   => ($need - $use)
          ];
        }
      }
    }

    // Record completion
    $stmt = $db->prepare("INSERT INTO completions (habit_id, completed_date, champion_day) VALUES (?, CURDATE(), ?)");
    $stmt->execute([$habitId, $dayOfWeek]);

    // Add XP
    $stmt = $db->prepare("UPDATE champion_progress SET xp = xp + ? WHERE champion_id = ?");
    $stmt->execute([(int)$habit['xp_reward'], (int)$champion['id']]);

    // Level up check
    $stmt = $db->prepare("SELECT xp, level FROM champion_progress WHERE champion_id = ? LIMIT 1");
    $stmt->execute([(int)$champion['id']]);
    $progress = $stmt->fetch();

    $leveledUp = false;
    $newLevel = (int)($progress['level'] ?? 1);
    $newXP = (int)($progress['xp'] ?? 0);

    $maxXP = $newLevel * 100;
    if ($newXP >= $maxXP) {
      $newXP -= $maxXP;
      $newLevel++;

      $stmt = $db->prepare("UPDATE champion_progress SET level = ?, xp = ? WHERE champion_id = ?");
      $stmt->execute([$newLevel, $newXP, (int)$champion['id']]);
      $leveledUp = true;
    }

    $db->commit();

    respond([
      'success'    => true,
      'leveled_up' => $leveledUp,
      'level'      => $newLevel,
      'xp'         => $newXP,
      'warnings'   => $warnings,
      'consumed'   => $consumed
    ]);

  } catch (Throwable $e) {
    if ($db->inTransaction()) $db->rollBack();
    respond(['success' => false, 'message' => 'Server error']);
  }
}

function completeBounty(): void {
  $bountyId = (int)($_POST['bounty_id'] ?? 0);
  if ($bountyId <= 0) respond(['success' => false, 'message' => 'Invalid bounty ID']);

  $db = getDB();
  $dayOfWeek = (int)date('w');

  try {
    $db->beginTransaction();

    // Ensure bounty exists and not completed
    $stmt = $db->prepare("SELECT xp_reward, completed FROM bounties WHERE id = ? LIMIT 1");
    $stmt->execute([$bountyId]);
    $bounty = $stmt->fetch();
    if (!$bounty) {
      $db->rollBack();
      respond(['success' => false, 'message' => 'Bounty not found']);
    }
    if (!empty($bounty['completed'])) {
      $db->rollBack();
      respond(['success' => false, 'message' => 'Bounty already completed']);
    }

    // Champion for today
    $stmt = $db->prepare("SELECT id FROM champions WHERE day_index = ? LIMIT 1");
    $stmt->execute([$dayOfWeek]);
    $champion = $stmt->fetch();
    if (!$champion) {
      $db->rollBack();
      respond(['success' => false, 'message' => 'Champion not found']);
    }

    // ✅ NEW: mark completed + store who completed it
    $stmt = $db->prepare("
      UPDATE bounties
      SET completed = TRUE,
          completed_date = CURDATE(),
          completed_by_champion_id = ?
      WHERE id = ?
    ");
    $stmt->execute([(int)$champion['id'], $bountyId]);

    // Add XP to that champion
    $stmt = $db->prepare("UPDATE champion_progress SET xp = xp + ? WHERE champion_id = ?");
    $stmt->execute([(int)$bounty['xp_reward'], (int)$champion['id']]);

    $db->commit();
    respond(['success' => true]);

  } catch (Throwable $e) {
    if ($db->inTransaction()) $db->rollBack();
    respond(['success' => false, 'message' => 'Server error']);
  }
}

function getItem(): void {
  $itemId = (int)($_GET['item_id'] ?? 0);
  if ($itemId <= 0) respond(['success' => false, 'message' => 'Invalid item ID']);

  $db = getDB();
  $stmt = $db->prepare("SELECT * FROM items WHERE id = ? LIMIT 1");
  $stmt->execute([$itemId]);
  $item = $stmt->fetch();

  if ($item) respond(['success' => true, 'data' => $item]);
  respond(['success' => false, 'message' => 'Item not found']);
}

function getDayDetails(): void {
  $date = trim($_GET['date'] ?? '');
  if ($date === '' || !validDateYmd($date)) respond(['success' => false, 'message' => 'Invalid date']);

  $db = getDB();
  $dayOfWeek = (int)date('w', strtotime($date));

  $stmt = $db->prepare("SELECT * FROM champions WHERE day_index = ? LIMIT 1");
  $stmt->execute([$dayOfWeek]);
  $champion = $stmt->fetch();

  $stmt = $db->prepare("
    SELECT h.name, h.image_path
    FROM completions c
    JOIN habits h ON c.habit_id = h.id
    WHERE c.completed_date = ?
    ORDER BY h.time_of_day ASC, h.name ASC
  ");
  $stmt->execute([$date]);
  $completions = $stmt->fetchAll();

  respond([
    'success' => true,
    'champion' => $champion ?: null,
    'completions' => $completions
  ]);
}