import { Router, Request, Response } from 'express';
import { query } from '../db/client';
import { MatchResponse } from '../types';
import { logger } from '../services/logger';
import { upsertUser } from '../services/userService';

const router = Router();

/**
 * GET /api/matches
 * Alle Spiele zurückgeben, mit dem Tipp des aktuellen Users (falls vorhanden)
 *
 * Query params:
 *   stage=GROUP_STAGE | ROUND_OF_16 | QUARTER_FINALS | SEMI_FINALS | FINAL
 *   group=GROUP_A ... GROUP_H
 */
router.get('/', async (req: Request, res: Response): Promise<void> => {
  const userId = req.staffbaseUser!.sub;
  const { stage, group } = req.query;

  // User beim ersten App-Aufruf automatisch anlegen / aktualisieren
  await upsertUser(req.staffbaseUser!);

  try {
    let whereClause = '';
    const params: unknown[] = [userId];

    if (stage) {
      params.push(stage);
      whereClause += ` AND m.stage = $${params.length}`;
    }
    if (group) {
      params.push(group);
      whereClause += ` AND m.group_name = $${params.length}`;
    }

    const rows = await query<{
      id: number;
      external_id: number;
      utc_date: Date;
      status: string;
      stage: string;
      group_name: string | null;
      home_team_name: string;
      home_team_short: string;
      home_team_crest: string | null;
      away_team_name: string;
      away_team_short: string;
      away_team_crest: string | null;
      score_home: number | null;
      score_away: number | null;
      tip_home: number | null;
      tip_away: number | null;
      tip_points: number | null;
    }>(
      `SELECT
        m.id, m.external_id, m.utc_date, m.status, m.stage, m.group_name,
        m.home_team_name, m.home_team_short, m.home_team_crest,
        m.away_team_name, m.away_team_short, m.away_team_crest,
        m.score_home, m.score_away,
        t.tip_home, t.tip_away, t.points AS tip_points
       FROM matches m
       LEFT JOIN tips t ON t.match_id = m.id AND t.user_id = $1
       WHERE 1=1 ${whereClause}
       ORDER BY m.utc_date ASC`,
      params
    );

    const now = new Date();

    const matches: MatchResponse[] = rows.map((row) => {
      const kickoff = new Date(row.utc_date);
      const minutesUntilKickoff = Math.floor(
        (kickoff.getTime() - now.getTime()) / 60000
      );
      // Tipps können bis 5 Minuten vor Anpfiff abgegeben werden
      const tippable = minutesUntilKickoff > 5 && (row.status === 'SCHEDULED' || row.status === 'TIMED');

      return {
        id: row.id,
        externalId: row.external_id,
        utcDate: row.utc_date.toISOString(),
        status: row.status as MatchResponse['status'],
        stage: row.stage,
        group: row.group_name,
        homeTeam: {
          name: row.home_team_name,
          shortName: row.home_team_short,
          crest: row.home_team_crest,
        },
        awayTeam: {
          name: row.away_team_name,
          shortName: row.away_team_short,
          crest: row.away_team_crest,
        },
        score: {
          home: row.score_home,
          away: row.score_away,
        },
        userTip:
          row.tip_home !== null
            ? {
                home: row.tip_home,
                away: row.tip_away!,
                points: row.tip_points,
              }
            : null,
        minutesUntilKickoff,
        tippable,
      };
    });

    res.json({ matches, count: matches.length });
  } catch (error) {
    logger.error('Failed to fetch matches', { error, userId });
    res.status(500).json({ error: 'Internal server error' });
  }
});

/**
 * GET /api/matches/:id
 * Ein einzelnes Spiel mit dem Tipp des Users
 */
router.get('/:id', async (req: Request, res: Response): Promise<void> => {
  const userId = req.staffbaseUser!.sub;
  const matchId = parseInt(req.params.id);

  if (isNaN(matchId)) {
    res.status(400).json({ error: 'Invalid match ID' });
    return;
  }

  try {
    const rows = await query<{
      id: number;
      external_id: number;
      utc_date: Date;
      status: string;
      stage: string;
      group_name: string | null;
      home_team_name: string;
      home_team_short: string;
      home_team_crest: string | null;
      away_team_name: string;
      away_team_short: string;
      away_team_crest: string | null;
      score_home: number | null;
      score_away: number | null;
      tip_home: number | null;
      tip_away: number | null;
      tip_points: number | null;
    }>(
      `SELECT
        m.id, m.external_id, m.utc_date, m.status, m.stage, m.group_name,
        m.home_team_name, m.home_team_short, m.home_team_crest,
        m.away_team_name, m.away_team_short, m.away_team_crest,
        m.score_home, m.score_away,
        t.tip_home, t.tip_away, t.points AS tip_points
       FROM matches m
       LEFT JOIN tips t ON t.match_id = m.id AND t.user_id = $1
       WHERE m.id = $2`,
      [userId, matchId]
    );

    if (rows.length === 0) {
      res.status(404).json({ error: 'Match not found' });
      return;
    }

    const row = rows[0];
    const kickoff = new Date(row.utc_date);
    const minutesUntilKickoff = Math.floor(
      (kickoff.getTime() - Date.now()) / 60000
    );

    res.json({
      id: row.id,
      externalId: row.external_id,
      utcDate: row.utc_date.toISOString(),
      status: row.status,
      stage: row.stage,
      group: row.group_name,
      homeTeam: { name: row.home_team_name, shortName: row.home_team_short, crest: row.home_team_crest },
      awayTeam: { name: row.away_team_name, shortName: row.away_team_short, crest: row.away_team_crest },
      score: { home: row.score_home, away: row.score_away },
      userTip: row.tip_home !== null
        ? { home: row.tip_home, away: row.tip_away, points: row.tip_points }
        : null,
      minutesUntilKickoff,
      tippable: minutesUntilKickoff > 5 && (row.status === 'SCHEDULED' || row.status === 'TIMED'),
    });
  } catch (error) {
    logger.error('Failed to fetch match', { error, matchId });
    res.status(500).json({ error: 'Internal server error' });
  }
});

export default router;
