import type { Database } from 'bun:sqlite';
import { ensureUserExists } from '../../db';
import { toIsoSqlUTC } from '../../utils/datetime';

/**
 * Reconciliación idempotente de membresías de un grupo.
 */
export function reconcileGroupMembers(
  db: Database,
  groupId: string,
  snapshot: Array<{ userId: string; isAdmin: boolean }>,
  nowIso?: string
): { added: number; updated: number; deactivated: number } {
  if (!groupId || !Array.isArray(snapshot)) {
    throw new Error('Invalid arguments for reconcileGroupMembers');
  }
  const now = nowIso || toIsoSqlUTC(new Date());
  let added = 0, updated = 0, deactivated = 0;

  const incoming = new Map<string, { isAdmin: boolean }>();
  for (const m of snapshot) {
    if (!m?.userId) continue;
    incoming.set(m.userId, { isAdmin: !!m.isAdmin });
  }

  db.transaction(() => {
    const existingRows = db.prepare(`
      SELECT user_id, is_admin, is_active 
      FROM group_members 
      WHERE group_id = ?
    `).all(groupId) as Array<{ user_id: string; is_admin: number; is_active: number }>;
    const existing = new Map(existingRows.map(r => [r.user_id, { isAdmin: !!r.is_admin, isActive: !!r.is_active }]));

    for (const [userId, { isAdmin }] of incoming.entries()) {
      ensureUserExists(userId, db);
      const row = existing.get(userId);
      if (!row) {
        db.prepare(`
          INSERT INTO group_members (group_id, user_id, is_admin, is_active, first_seen_at, last_seen_at)
          VALUES (?, ?, ?, 1, ?, ?)
        `).run(groupId, userId, isAdmin ? 1 : 0, now, now);
        added++;
      } else {
        const roleChanged = row.isAdmin !== isAdmin;
        if (!row.isActive || roleChanged) {
          db.prepare(`
            UPDATE group_members
            SET is_active = 1,
                is_admin = ?,
                last_seen_at = ?,
                last_role_change_at = CASE WHEN ? THEN ? ELSE last_role_change_at END
            WHERE group_id = ? AND user_id = ?
          `).run(isAdmin ? 1 : 0, now, roleChanged ? 1 : 0, roleChanged ? now : null, groupId, userId);
          updated++;
        } else {
          db.prepare(`
            UPDATE group_members
            SET last_seen_at = ?
            WHERE group_id = ? AND user_id = ?
          `).run(now, groupId, userId);
        }
      }
    }

    for (const [userId, state] of existing.entries()) {
      if (!incoming.has(userId) && state.isActive) {
        db.prepare(`
          UPDATE group_members
          SET is_active = 0,
              last_seen_at = ?
          WHERE group_id = ? AND user_id = ?
        `).run(now, groupId, userId);
        deactivated++;
      }
    }
  })();

  return { added, updated, deactivated };
}
