<?php
declare(strict_types=1);

/** ========== CORS MUST COME FIRST ========== */
require_once __DIR__ . '/_cors.php';
header('Content-Type: application/json; charset=utf-8');

/** ========== CONFIG ========== */
$debug = false; // set true ONLY in dev

/** ========== HELPERS ========== */
function respond(int $status, array $payload): void {
  http_response_code($status);
  echo json_encode($payload, JSON_UNESCAPED_SLASHES);
  exit;
}

function cookieNames(): array {
  return array_values(array_keys($_COOKIE ?? [])); // keys only (safe)
}

function pickSessionName(): ?string {
  if (!empty($_COOKIE['PHPSESSADM'])) return 'PHPSESSADM';
  if (!empty($_COOKIE['PHPSESSCLI'])) return 'PHPSESSCLI';
  if (!empty($_COOKIE['PHPSESSAFF'])) return 'PHPSESSAFF';
  return null;
}

/** ---------- role helpers (adjust strings to match your DB) ---------- */
function roleIs(array $user, array $roles): bool {
  $r = strtolower((string)($user['role'] ?? ''));
  foreach ($roles as $x) if ($r === strtolower($x)) return true;
  return false;
}
function isSuperAdmin(array $u): bool { return roleIs($u, ['super_admin','superadmin']); }
function isNational(array $u): bool { return roleIs($u, ['national','national_leader']); }
function isCounty(array $u): bool { return roleIs($u, ['county','county_rep']); }
function isConstituency(array $u): bool { return roleIs($u, ['constituency','constituency_rep']); }
function isWard(array $u): bool { return roleIs($u, ['ward','ward_rep']); }

function isMember(PDO $db, int $roomId, int $userId): bool {
  $st = $db->prepare("SELECT 1 FROM pth_party_room_members WHERE room_id=:rid AND user_id=:uid LIMIT 1");
  $st->execute([':rid'=>$roomId, ':uid'=>$userId]);
  return (bool)$st->fetchColumn();
}

/**
 * Scope access for hierarchy rooms.
 * NOTE: Everyone can see national rooms by default (policy).
 * Change if you want leadership-only.
 */
function canAccessScopeRoom(array $user, array $room): bool {
  if (isSuperAdmin($user)) return true;
  if (isNational($user)) return true;

  $scope = (string)($room['scope_level'] ?? '');
  if ($scope === 'national') return true;

  $uCounty = (int)($user['county_id'] ?? 0);
  $uConst  = (int)($user['constituency_id'] ?? 0);
  $uWard   = (int)($user['ward_id'] ?? 0);
  $uPs     = (int)($user['polling_station_id'] ?? 0);

  $rCounty = (int)($room['county_id'] ?? 0);
  $rConst  = (int)($room['constituency_id'] ?? 0);
  $rWard   = (int)($room['ward_id'] ?? 0);
  $rPs     = (int)($room['polling_station_id'] ?? 0);

  if ($scope === 'county') return $uCounty > 0 && $uCounty === $rCounty;

  if ($scope === 'constituency') {
    if (isCounty($user)) return $uCounty > 0 && $uCounty === $rCounty;
    return $uConst > 0 && $uConst === $rConst;
  }

  if ($scope === 'ward') {
    if (isCounty($user)) return $uCounty > 0 && $uCounty === $rCounty;
    if (isConstituency($user)) return $uConst > 0 && $uConst === $rConst;
    return $uWard > 0 && $uWard === $rWard;
  }

  if ($scope === 'polling_station') {
    if (isCounty($user)) return $uCounty > 0 && $uCounty === $rCounty;
    if (isConstituency($user)) return $uConst > 0 && $uConst === $rConst;
    if (isWard($user)) return $uWard > 0 && $uWard === $rWard;
    return $uPs > 0 && $uPs === $rPs;
  }

  return false;
}

/** ========== DB CONNECTION ========== */
$connPath = __DIR__ . '/conn.php';
if (!file_exists($connPath)) {
  respond(500, [
    'error' => 'conn.php not found',
    'path'  => $connPath,
    'dir'   => __DIR__,
  ]);
}
require_once $connPath; // expects $db (PDO)

/** ========== SESSION (MUST BE BEFORE AUTH CHECK) ========== */
$sessionName = pickSessionName();
if (!$sessionName) {
  respond(401, [
    'error' => 'Not authenticated (no valid session cookie)',
    'cookie_names' => cookieNames(),
    'hint' => 'Frontend must send cookies (fetch: credentials:"include" / axios: withCredentials:true).',
  ]);
}

session_name($sessionName);
session_start();

$userId = (int)($_SESSION['user_id'] ?? 0);
if ($userId <= 0) $userId = (int)($_SESSION['SESS_MEMBER_ID'] ?? 0);

if ($userId <= 0) {
  respond(401, [
    'error' => 'Not authenticated',
    'session' => $sessionName,
    'present_session_keys' => $debug ? array_keys($_SESSION ?? []) : [],
  ]);
}

/** ========== LOAD USER CONTEXT ========== */
$uStmt = $db->prepare("
  SELECT id, role, name, county_id, constituency_id, ward_id, polling_station_id
  FROM users
  WHERE id = :uid
  LIMIT 1
");
$uStmt->execute([':uid' => $userId]);
$user = $uStmt->fetch(PDO::FETCH_ASSOC);
if (!$user) respond(401, ['error' => 'User not found']);

$countyId = (int)($user['county_id'] ?? 0);
$constId  = (int)($user['constituency_id'] ?? 0);
$wardId   = (int)($user['ward_id'] ?? 0);
$psId     = (int)($user['polling_station_id'] ?? 0);

try {
  /**
   * ===========================
   * 1) AUTO-HEAL DM MEMBERSHIP
   * ===========================
   * If room is DM with room_key "dm:A_B", ensure BOTH A and B exist in members.
   * This prevents "missing messages on refresh" when membership-based lists are used.
   */
  $repairSql = "
    INSERT IGNORE INTO pth_party_room_members (room_id, user_id, role)
    SELECT
      r.id AS room_id,
      other.other_user_id,
      'member' AS role
    FROM pth_party_room r
    JOIN pth_party_room_members rm_me
      ON rm_me.room_id = r.id AND rm_me.user_id = :uid
    JOIN (
      SELECT
        r2.id AS room_id,
        CASE
          WHEN CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(r2.room_key, ':', -1), '_', 1) AS UNSIGNED) = :uid
            THEN CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(r2.room_key, ':', -1), '_', -1) AS UNSIGNED)
          ELSE
            CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(r2.room_key, ':', -1), '_', 1) AS UNSIGNED)
        END AS other_user_id
      FROM pth_party_room r2
      WHERE r2.room_type = 'dm'
        AND r2.room_key LIKE 'dm:%_%'
    ) other
      ON other.room_id = r.id
    JOIN users u_other
      ON u_other.id = other.other_user_id
    WHERE r.room_type = 'dm'
      AND NOT EXISTS (
        SELECT 1
        FROM pth_party_room_members rm2
        WHERE rm2.room_id = r.id AND rm2.user_id = other.other_user_id
      )
  ";
  $stmtRepair = $db->prepare($repairSql);
  $stmtRepair->execute([':uid' => $userId]);

  /**
   * ======================================
   * 2) GET ALL ROOMS USER CAN SEE (MEM + SCOPE)
   * ======================================
   */
  $sqlRooms = "
    SELECT DISTINCT r.id AS roomId
    FROM pth_party_room r
    JOIN pth_party_room_members rm ON rm.room_id = r.id
    WHERE rm.user_id = :uid

    UNION DISTINCT
    SELECT r.id AS roomId
    FROM pth_party_room r
    WHERE r.scope_level = 'national'

    UNION DISTINCT
    SELECT r.id AS roomId
    FROM pth_party_room r
    WHERE r.scope_level = 'county' AND r.county_id = :county_id

    UNION DISTINCT
    SELECT r.id AS roomId
    FROM pth_party_room r
    WHERE r.scope_level = 'constituency' AND r.constituency_id = :const_id

    UNION DISTINCT
    SELECT r.id AS roomId
    FROM pth_party_room r
    WHERE r.scope_level = 'ward' AND r.ward_id = :ward_id

    UNION DISTINCT
    SELECT r.id AS roomId
    FROM pth_party_room r
    WHERE r.scope_level = 'polling_station' AND r.polling_station_id = :ps_id
  ";

  $stmtRooms = $db->prepare($sqlRooms);
  $stmtRooms->execute([
    ':uid' => $userId,
    ':county_id' => $countyId,
    ':const_id' => $constId,
    ':ward_id' => $wardId,
    ':ps_id' => $psId,
  ]);

  $roomIds = array_map(fn($r) => (int)$r['roomId'], $stmtRooms->fetchAll(PDO::FETCH_ASSOC));
  $roomIds = array_values(array_unique(array_filter($roomIds, fn($x) => $x > 0)));

  if (!$roomIds) {
    respond(200, ['conversations' => []]);
  }

  $in = implode(',', array_fill(0, count($roomIds), '?'));

  /**
   * ======================================
   * 3) MAIN QUERY: ROOM META + LAST MESSAGE
   * ======================================
   * Performance: assumes INDEX(room_id, id) on pth_party_messages
   */
  $sql = "
    SELECT
      r.id AS roomId,
      r.room_key AS roomKey,
      r.room_name AS roomTitle,
      r.room_type AS roomType,
      r.scope_level AS scopeLevel,
      r.created_at AS roomCreatedAt,

      lm.body AS lastMessage,
      lm.created_at AS updatedAt

    FROM pth_party_room r

    LEFT JOIN pth_party_messages lm
      ON lm.id = (
        SELECT id
        FROM pth_party_messages
        WHERE room_id = r.id
          AND (is_deleted = 0 OR is_deleted IS NULL)
        ORDER BY id DESC
        LIMIT 1
      )

    WHERE r.id IN ($in)
    ORDER BY COALESCE(lm.created_at, r.created_at) DESC
  ";

  $stmt = $db->prepare($sql);
  $stmt->execute($roomIds);
  $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

  /**
   * ======================================
   * 4) PARTICIPANTS (ONLY FOR MEMBERSHIP ROOMS)
   * ======================================
   */
  $sqlParts = "
    SELECT
      rm.room_id AS roomId,
      COUNT(*) AS memberCount,
      GROUP_CONCAT(u.name ORDER BY u.name SEPARATOR ', ') AS participantsCsv,
      MAX(CASE WHEN rm.user_id <> ? THEN u.name END) AS dmOtherName
    FROM pth_party_room_members rm
    JOIN users u ON u.id = rm.user_id
    WHERE rm.room_id IN ($in)
    GROUP BY rm.room_id
  ";

  $paramsParts = [];
  $paramsParts[] = $userId;
  foreach ($roomIds as $rid) $paramsParts[] = $rid;

  $stmtParts = $db->prepare($sqlParts);
  $stmtParts->execute($paramsParts);
  $partRows = $stmtParts->fetchAll(PDO::FETCH_ASSOC);

  $partsByRoom = [];
  foreach ($partRows as $pr) {
    $partsByRoom[(int)$pr['roomId']] = $pr;
  }

  $conversations = [];

  foreach ($rows as $row) {
    $roomId = (int)($row['roomId'] ?? 0);
    $roomType = (string)($row['roomType'] ?? '');
    $scopeLevel = (string)($row['scopeLevel'] ?? '');

    $participants = [];
    $memberCount = 0;
    $dmOtherName = '';

    // Only DM/custom rooms will show participants
    if ($roomType === 'dm' || $scopeLevel === 'custom') {
      $pr = $partsByRoom[$roomId] ?? null;
      $memberCount = (int)($pr['memberCount'] ?? 0);

      $csv = trim((string)($pr['participantsCsv'] ?? ''));
      if ($csv !== '') {
        $participants = array_values(array_filter(array_map('trim', explode(',', $csv))));
      }

      $dmOtherName = trim((string)($pr['dmOtherName'] ?? ''));
    }

    $displayTitle = (string)($row['roomTitle'] ?? '');
    if ($roomType === 'dm' && $dmOtherName !== '') {
      $displayTitle = $dmOtherName;
    }

    $label =
      $roomType === 'announcement' ? 'Announcement' :
      ($roomType === 'group' ? 'Group' : 'Conversation');

    $conversations[] = [
      'roomId'       => (string)($row['roomId'] ?? ''),
      'roomKey'      => $row['roomKey'] ?? null,
      'roomType'     => $roomType,
      'scopeLevel'   => $scopeLevel,

      'title'        => $displayTitle,
      'roomTitle'    => $row['roomTitle'] ?? null,
      'label'        => $label,

      'participants' => $participants,
      'memberCount'  => $memberCount,

      'lastMessage'  => $row['lastMessage'] ?? '—',
      'updatedAt'    => $row['updatedAt'] ?? ($row['roomCreatedAt'] ?? null),

      'unread'       => false,
      'archived'     => false,
    ];
  }

  respond(200, ['conversations' => $conversations]);

} catch (Throwable $e) {
  if ($debug) {
    respond(500, [
      'error'   => 'conversations_failed',
      'message' => $e->getMessage(),
    ]);
  }
  respond(500, ['error' => 'conversations_failed']);
}
