import { NextRequest, NextResponse } from 'next/server';
import { getDb } from '@/lib/db';
import { getUnfinishedParticipants } from '@/lib/restaurant-filter';
import { jokerSchema, parseBody } from '@/lib/validation';

export async function POST(req: NextRequest, { params }: { params: Promise<{ code: string }> }) {
  const { code } = await params;
  const parsed = await parseBody(req, jokerSchema);
  if (!parsed.success) return parsed.response;

  const { participantId } = parsed.data;
  const db = getDb();

  const session = db.prepare('SELECT * FROM sessions WHERE code = ?').get(code) as any;
  if (!session) return NextResponse.json({ error: 'Session nicht gefunden' }, { status: 404 });

  const alreadyDrawn = db
    .prepare('SELECT COUNT(*) as cnt FROM joker_draws WHERE session_id = ?')
    .get(session.id) as { cnt: number };
  if (alreadyDrawn.cnt > 0) {
    return NextResponse.json({ error: 'Der Schicksals-Joker wurde in dieser Session bereits gezogen' }, { status: 400 });
  }

  const requester = db.prepare('SELECT * FROM participants WHERE id = ?').get(participantId) as any;
  if (!requester || requester.session_id !== session.id || requester.is_active !== 1) {
    return NextResponse.json({ error: 'Nicht berechtigt' }, { status: 403 });
  }

  const activeCreator = db
    .prepare('SELECT * FROM participants WHERE session_id = ? AND is_creator = 1 AND is_active = 1')
    .get(session.id) as any;

  const isAllowed = requester.is_creator === 1 || !activeCreator;
  if (!isAllowed) {
    return NextResponse.json(
      { error: 'Nur der Session-Ersteller darf den Joker ziehen (oder jemand anderes, falls dieser die Session verlassen hat)' },
      { status: 403 }
    );
  }

  // Harter Gate: Der Joker darf erst gezogen werden, wenn ALLE aktiven
  // Teilnehmer alle verfuegbaren Karten geswipet haben. Sonst koennte der
  // Host jokern, waehrend andere noch mitten im Stapel sind.
  const unfinished = getUnfinishedParticipants(db, session);
  if (unfinished.length > 0) {
    return NextResponse.json(
      {
        error: 'Nicht alle Teilnehmer haben ihre Karten geswipet',
        unfinished: unfinished.map((p) => p.display_name || 'Jemand'),
      },
      { status: 409 }
    );
  }

  const yesCandidates = db.prepare(`
    SELECT s.restaurant_id, COUNT(*) as yes_count
    FROM swipes s
    WHERE s.session_id = ? AND s.direction = 'yes'
      AND NOT EXISTS (
        SELECT 1 FROM matches m WHERE m.session_id = s.session_id AND m.restaurant_id = s.restaurant_id
      )
      AND NOT EXISTS (
        SELECT 1 FROM vetos v WHERE v.session_id = s.session_id AND v.restaurant_id = s.restaurant_id
      )
    GROUP BY s.restaurant_id
  `).all(session.id) as { restaurant_id: number; yes_count: number }[];

  let chosenRestaurantId: number;
  let yesCount = 0;
  let isForcedChoice = false;
  let poolCount = 0;

  if (yesCandidates.length > 0) {
    poolCount = yesCandidates.length;
    const totalWeight = yesCandidates.reduce((sum, c) => sum + c.yes_count, 0);
    let rnd = Math.random() * totalWeight;
    let chosen = yesCandidates[0];
    for (const c of yesCandidates) {
      rnd -= c.yes_count;
      if (rnd <= 0) { chosen = c; break; }
    }
    chosenRestaurantId = chosen.restaurant_id;
    yesCount = chosen.yes_count;
  } else {
    const seen = db.prepare(`
      SELECT DISTINCT s.restaurant_id FROM swipes s
      WHERE s.session_id = ?
        AND NOT EXISTS (
          SELECT 1 FROM matches m WHERE m.session_id = s.session_id AND m.restaurant_id = s.restaurant_id
        )
        AND NOT EXISTS (
          SELECT 1 FROM vetos v WHERE v.session_id = s.session_id AND v.restaurant_id = s.restaurant_id
        )
    `).all(session.id) as { restaurant_id: number }[];

    if (seen.length === 0) {
      return NextResponse.json(
        { error: 'Alle geswipeten Restaurants haben bereits ein Match, wurden per Veto ausgeschlossen, oder es wurde noch nichts geswiped - der Joker kann nichts Neues entscheiden' },
        { status: 400 }
      );
    }
    const pick = seen[Math.floor(Math.random() * seen.length)];
    chosenRestaurantId = pick.restaurant_id;
    isForcedChoice = true;
    poolCount = seen.length;
  }

  const activeParticipantCount = (
    db.prepare('SELECT COUNT(*) as cnt FROM participants WHERE session_id = ? AND is_active = 1').get(session.id) as any
  ).cnt;

  // BUGFIX (v24): echten Prozentwert einmal zentral berechnen und sowohl in
  // die DB schreiben ALS AUCH in der API-Antwort mitgeben (matchPercentage).
  // Vorher wurde dieser Wert nur in die DB geschrieben - das Frontend
  // (app/session/[code]/page.tsx) kannte ihn nicht und hat beim Joker-Ziehen
  // hart 100 (bzw. 0 bei Forced Choice) gesetzt. Dadurch zeigte der Joker-
  // Screen beim "gejokerten" Restaurant immer 100% an, auch wenn real nur
  // z.B. 1 von 4 Personen zugestimmt hatte.
  const realMatchPercentage = isForcedChoice
    ? 0
    : (activeParticipantCount > 0 ? (yesCount / activeParticipantCount) * 100 : 0);

  db.prepare('INSERT INTO joker_draws (session_id, restaurant_id) VALUES (?, ?)').run(session.id, chosenRestaurantId);

  db.prepare(`
    INSERT INTO matches (session_id, restaurant_id, yes_count, active_participant_count, match_percentage, is_joker_result, pool_count)
    VALUES (?, ?, ?, ?, ?, 1, ?)
    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,
      is_joker_result = 1,
      pool_count = excluded.pool_count,
      created_at = datetime('now')
  `).run(
    session.id,
    chosenRestaurantId,
    yesCount,
    activeParticipantCount,
    realMatchPercentage,
    poolCount
  );

  const restaurant = db.prepare(`
    SELECT r.*, sp.reservation_url as reservation_url, sp.image_url as sponsor_image_url
    FROM restaurants r
    LEFT JOIN sponsored_restaurants sp ON sp.restaurant_id = r.id
    WHERE r.id = ?
  `).get(chosenRestaurantId) as any;
  return NextResponse.json({
    restaurant: { ...restaurant, city: session.city },
    yesCount,
    isForcedChoice,
    matchPercentage: realMatchPercentage,
    poolCount,
  });
}
