// ABOUTME: REST API routes for race data access
// ABOUTME: Provides listing, detail, runners, results, and dividends endpoints

import { Router, Request, Response } from 'express';
import { PrismaClient } from '@prisma/client';
import logger from '../utils/logger';

export function createRacesRouter(prisma: PrismaClient): Router {
  const router = Router();

  /**
   * GET /api/races
   * Query params: date, meetingId, status, limit, offset
   * Returns: Paginated list of races
   */
  router.get('/', async (req: Request, res: Response) => {
    try {
      const { date, meetingId, status } = req.query;

      // Pagination params
      let limit = req.query.limit ? parseInt(req.query.limit as string, 10) : 50;
      if (isNaN(limit) || limit < 1) limit = 50;
      if (limit > 200) limit = 200;

      let offset = req.query.offset ? parseInt(req.query.offset as string, 10) : 0;
      if (isNaN(offset) || offset < 0) offset = 0;

      // Build where clause
      const where: Record<string, unknown> = {};

      if (date) {
        const dateStr = date as string;
        const startDate = new Date(dateStr);
        if (isNaN(startDate.getTime())) {
          return res.status(400).json({ error: 'Invalid date parameter. Use YYYY-MM-DD format.' });
        }
        const endDate = new Date(startDate);
        endDate.setDate(endDate.getDate() + 1);
        where.startTime = { gte: startDate, lt: endDate };
      }

      if (meetingId) {
        where.meetingId = meetingId as string;
      }

      if (status) {
        where.status = status as string;
      }

      logger.debug({ filters: where, limit, offset }, 'Fetching races');

      const [total, races] = await Promise.all([
        prisma.race.count({ where }),
        prisma.race.findMany({
          where,
          include: {
            meeting: {
              select: {
                id: true,
                name: true,
                date: true,
                country: true,
                category: true,
              },
            },
            _count: {
              select: {
                runners: true,
                results: true,
              },
            },
          },
          take: limit,
          skip: offset,
          orderBy: { startTime: 'desc' },
        }),
      ]);

      const hasMore = offset + limit < total;

      const data = races.map((r) => ({
        id: r.id,
        meetingId: r.meetingId,
        raceNumber: r.raceNumber,
        name: r.name,
        startTime: r.startTime,
        distance: r.distance,
        status: r.status,
        country: r.country,
        state: r.state,
        trackCondition: r.trackCondition,
        weather: r.weather,
        meeting: r.meeting,
        runnerCount: r._count.runners,
        resultCount: r._count.results,
      }));

      logger.debug({ count: data.length, total }, 'Races fetched successfully');

      return res.json({
        data,
        meta: { total, limit, offset, hasMore },
      });
    } catch (error) {
      logger.error({ error }, 'Failed to fetch races');
      return res.status(500).json({
        error: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  });

  /**
   * GET /api/races/:id
   * Returns: Race detail with meeting info
   */
  router.get('/:id', async (req: Request, res: Response) => {
    try {
      const id = req.params.id as string;

      logger.debug({ raceId: id }, 'Fetching race by ID');

      const race = await prisma.race.findUnique({
        where: { id },
        include: {
          meeting: true,
          _count: {
            select: {
              runners: true,
              results: true,
              dividends: true,
            },
          },
        },
      });

      if (!race) {
        return res.status(404).json({ error: 'Race not found' });
      }

      return res.json({ data: race });
    } catch (error) {
      logger.error({ error, raceId: req.params.id }, 'Failed to fetch race');
      return res.status(500).json({
        error: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  });

  /**
   * GET /api/races/:id/runners
   * Returns: List of runners for a race (include horse details)
   */
  router.get('/:id/runners', async (req: Request, res: Response) => {
    try {
      const id = req.params.id as string;

      logger.debug({ raceId: id }, 'Fetching runners for race');

      // Check if race exists
      const race = await prisma.race.findUnique({
        where: { id },
        select: { id: true },
      });

      if (!race) {
        return res.status(404).json({ error: 'Race not found' });
      }

      const runners = await prisma.runner.findMany({
        where: { raceId: id },
        include: {
          horse: {
            select: {
              id: true,
              name: true,
              normalizedName: true,
              sex: true,
              colour: true,
              sire: true,
              dam: true,
            },
          },
        },
        orderBy: { runnerNumber: 'asc' },
      });

      return res.json({ data: runners });
    } catch (error) {
      logger.error({ error, raceId: req.params.id }, 'Failed to fetch runners');
      return res.status(500).json({
        error: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  });

  /**
   * GET /api/races/:id/results
   * Returns: Race results (finish positions, margins, times)
   */
  router.get('/:id/results', async (req: Request, res: Response) => {
    try {
      const id = req.params.id as string;

      logger.debug({ raceId: id }, 'Fetching results for race');

      // Check if race exists
      const race = await prisma.race.findUnique({
        where: { id },
        select: { id: true },
      });

      if (!race) {
        return res.status(404).json({ error: 'Race not found' });
      }

      const results = await prisma.result.findMany({
        where: { raceId: id },
        include: {
          runner: {
            select: {
              runnerNumber: true,
              horseName: true,
              barrier: true,
              scratched: true,
              horse: {
                select: {
                  id: true,
                  name: true,
                },
              },
            },
          },
        },
        orderBy: [{ finishPosition: { sort: 'asc', nulls: 'last' } }],
      });

      return res.json({ data: results });
    } catch (error) {
      logger.error({ error, raceId: req.params.id }, 'Failed to fetch results');
      return res.status(500).json({
        error: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  });

  /**
   * GET /api/races/:id/dividends
   * Returns: Dividends for a race (win, place, quinella, etc.)
   */
  router.get('/:id/dividends', async (req: Request, res: Response) => {
    try {
      const id = req.params.id as string;

      logger.debug({ raceId: id }, 'Fetching dividends for race');

      // Check if race exists
      const race = await prisma.race.findUnique({
        where: { id },
        select: { id: true },
      });

      if (!race) {
        return res.status(404).json({ error: 'Race not found' });
      }

      const dividends = await prisma.dividend.findMany({
        where: { raceId: id },
        orderBy: [{ tote: 'asc' }, { productName: 'asc' }],
      });

      return res.json({ data: dividends });
    } catch (error) {
      logger.error({ error, raceId: req.params.id }, 'Failed to fetch dividends');
      return res.status(500).json({
        error: error instanceof Error ? error.message : 'Unknown error',
      });
    }
  });

  return router;
}
