import type Database from 'better-sqlite3';

export interface MatchResult {
  restaurantId: number;
  yesCount: number;
  activeParticipantCount: number;
  matchPercentage: number;
  isMatch: boolean;
}

// Match-Formel: 2 Teilnehmer -> beide Ja; ab 3 Teilnehmern -> mind. 2/3 der aktiven Mitglieder.
export function evaluateMatch(
  db: Database.Database,
  sessionId: number,
  restaurantId: number,
): MatchResult {
  // Ein per Veto ausgeschlossenes Restaurant darf niemals matchen - auch nicht,
  // wenn zufaellig genug "Ja"-Stimmen zusammenkommen. Das kann passieren, wenn
  // ein Teilnehmer die Karte schon VOR dem Veto eines anderen in seinem lokalen
  // Stapel hatte (Stapel wird pro Client einmal geladen, nicht live synchron
  // aktualisiert) und erst danach noch "Ja" swiped. Das Veto ist session-weit
  // final, unabhaengig davon, wie viele Ja-Stimmen zusaetzlich eintrudeln.
  const isVetoed = (
    db.prepare(`SELECT COUNT(*) as c FROM vetos WHERE session_id = ? AND restaurant_id = ?`)
      .get(sessionId, restaurantId) as { c: number }
  ).c > 0;

  const activeParticipantCount = (
    db.prepare('SELECT COUNT(*) as c FROM participants WHERE session_id = ? AND is_active = 1')
      .get(sessionId) as { c: number }
  ).c;

  // Ja-Stimmen UND abgegebene Stimmen (yes|no) NUR von aktiven Teilnehmern.
  // Vetos laufen separat ueber die vetos-Tabelle und zaehlen hier nicht mit.
  const votes = db.prepare(
    `SELECT
       SUM(CASE WHEN s.direction = 'yes' THEN 1 ELSE 0 END) AS yes_count,
       COUNT(*) AS voted_count
     FROM swipes s
     JOIN participants p ON p.id = s.participant_id
     WHERE s.session_id = ? AND s.restaurant_id = ? AND p.is_active = 1`
  ).get(sessionId, restaurantId) as { yes_count: number; voted_count: number };

  const yesCount = votes.yes_count ?? 0;
  const votedCount = votes.voted_count ?? 0;

  const matchPercentage = activeParticipantCount > 0 ? (yesCount / activeParticipantCount) * 100 : 0;

  let isMatch = false;
  if (!isVetoed) {
    // Quorum: eine Karte darf erst matchen, wenn ALLE aktiven Teilnehmer
    // abgestimmt haben (yes ODER no). So kann ein schnelles Paar keine
    // Mehrheit erreichen, bevor der Rest die Karte ueberhaupt gesehen hat -
    // wichtig seit der Kartenstapel pro Teilnehmer gemischt wird.
    const allVoted = votedCount >= activeParticipantCount;
    if (allVoted) {
      if (activeParticipantCount === 2) {
        isMatch = yesCount === 2;
      } else if (activeParticipantCount >= 3) {
        isMatch = yesCount / activeParticipantCount >= 2 / 3;
      }
    }
  }

  if (isMatch) {
    db.prepare(
      `INSERT INTO matches (session_id, restaurant_id, yes_count, active_participant_count, match_percentage)
       VALUES (?, ?, ?, ?, ?)
       ON CONFLICT(session_id, restaurant_id) DO UPDATE SET
         yes_count = excluded.yes_count,
         active_participant_count = excluded.active_participant_count,
         match_percentage = excluded.match_percentage`
    ).run(sessionId, restaurantId, yesCount, activeParticipantCount, matchPercentage);
  }

  return { restaurantId, yesCount, activeParticipantCount, matchPercentage, isMatch };
}
