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

const router = Router();

/**
 * POST /api/tips
 * Tipp für ein Spiel abgeben oder aktualisieren (UPSERT)
 *
 * Body: { matchId: number, tipHome: number, tipAway: number }
 */
router.post('/', async (req: Request, res: Response): Promise<void> => {
  const userId = req.staffbaseUser!.sub;
  const { matchId, tipHome, tipAway } = req.body as TipSubmitRequest;

  // Input-Validierung
  if (
    typeof matchId !== 'number' ||
    typeof tipHome !== 'number' ||
    typeof tipAway !== 'number' ||
    tipHome < 0 ||
    tipAway < 0 ||
    tipHome > 99 ||
    tipAway > 99 ||
    !Number.isInteger(tipHome) ||
    !Number.isInteger(tipAway)
  ) {
    res.status(400).json({
      error: 'Invalid tip',
      message: 'tipHome and tipAway must be integers between 0 and 99',
    });
    return;
  }

  try {
    await withTransaction(async (client) => {
      // Prüfen ob das Spiel noch tippbar ist
      const matchRows = await client.query<{
        id: number;
        utc_date: Date;
        status: string;
      }>(
        'SELECT id, utc_date, status FROM matches WHERE id = $1',
        [matchId]
      );

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

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

      if (minutesUntilKickoff <= 5) {
        res.status(409).json({
          error: 'Tip deadline passed',
          message: 'Tipps können nur bis 5 Minuten vor Anpfiff abgegeben werden.',
        });
        return;
      }

      if (match.status !== 'SCHEDULED' && match.status !== 'TIMED') {
        res.status(409).json({
          error: 'Match not tippable',
          message: 'Für dieses Spiel können keine Tipps mehr abgegeben werden.',
        });
        return;
      }

      // Sicherstellen, dass der User in der Datenbank existiert (Fallback)
      await upsertUser(req.staffbaseUser!);

      // Tipp anlegen oder aktualisieren (UPSERT)
      const result = await client.query<{
        tip_home: number;
        tip_away: number;
      }>(
        `INSERT INTO tips (user_id, match_id, tip_home, tip_away)
         VALUES ($1, $2, $3, $4)
         ON CONFLICT (user_id, match_id) DO UPDATE SET
           tip_home = EXCLUDED.tip_home,
           tip_away = EXCLUDED.tip_away,
           points = NULL,
           updated_at = NOW()
         RETURNING tip_home, tip_away`,
        [userId, matchId, tipHome, tipAway]
      );

      const tip = result.rows[0];
      const response: TipSubmitResponse = {
        success: true,
        tip: {
          home: tip.tip_home,
          away: tip.tip_away,
          points: null,
        },
        message: `Tipp ${tipHome}:${tipAway} gespeichert!`,
      };

      logger.info('Tip saved', { userId, matchId, tipHome, tipAway });
      res.status(201).json(response);
    });
  } catch (error) {
    logger.error('Failed to save tip', { error, userId, matchId });
    res.status(500).json({ error: 'Internal server error' });
  }
});

/**
 * GET /api/tips
 * Alle Tipps des aktuellen Users
 */
router.get('/', async (req: Request, res: Response): Promise<void> => {
  const userId = req.staffbaseUser!.sub;

  try {
    const tips = await query<{
      match_id: number;
      tip_home: number;
      tip_away: number;
      points: number | null;
      utc_date: Date;
      home_team_short: string;
      away_team_short: string;
      status: string;
    }>(
      `SELECT
         t.match_id, t.tip_home, t.tip_away, t.points,
         m.utc_date, m.home_team_short, m.away_team_short, m.status
       FROM tips t
       JOIN matches m ON m.id = t.match_id
       WHERE t.user_id = $1
       ORDER BY m.utc_date ASC`,
      [userId]
    );

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

export default router;
