#!/usr/bin/env python3
"""
Courses routes for API v1.

GET /api/v1/courses/today          — liste des courses du jour (public, paginated)
GET /api/v1/courses/{id}/predictions — prédictions ML pour une course (free tier, 1/day limit)
"""

import os
from datetime import datetime, timedelta
from flask import Blueprint, jsonify, request, g

from api_v1.utils import (
    get_db,
    table_exists,
    error_response,
    bad_request,
    not_found,
    internal_error,
    get_pagination_params,
    paginate_query,
)
from auth import jwt_required_middleware, free_daily_limit_check

courses_bp = Blueprint("v1_courses", __name__, url_prefix="/api/v1/courses")


# ──────────────────────────────────────────────────────────────
# GET /api/v1/courses/today
# ──────────────────────────────────────────────────────────────


@courses_bp.route("/today", methods=["GET"])
@jwt_required_middleware
def courses_today():
    """
    Courses du jour
    ---
    tags:
      - Courses
    summary: Liste toutes les courses du jour avec info course
    security:
      - Bearer: []
    parameters:
      - name: filter
        in: query
        type: string
        enum: [all, quinte, trot, plat]
        default: all
        description: Filtre par type de course
      - name: limit
        in: query
        type: integer
        default: 20
      - name: offset
        in: query
        type: integer
        default: 0
    responses:
      200:
        description: Liste des courses du jour
      401:
        description: Token manquant ou invalide
    """
    race_filter = request.args.get("filter", "all").lower()
    limit, offset = get_pagination_params(default_limit=50, max_limit=200)
    today = datetime.now().strftime("%Y-%m-%d")

    # Build SQL condition
    if race_filter == "quinte":
        cond = "AND (c.libelle LIKE '%Quinté%' OR c.libelle LIKE '%Quinte%')"
    elif race_filter == "trot":
        cond = "AND c.discipline LIKE '%Trot%'"
    elif race_filter == "plat":
        cond = "AND c.discipline LIKE '%Plat%'"
    else:
        cond = ""

    conn = get_db()
    try:
        # Graceful handling if pmu_courses table doesn't exist yet
        if not table_exists(conn, "pmu_courses"):
            return jsonify(
                {
                    "status": "ok",
                    "date": today,
                    "filter": race_filter,
                    "courses": [],
                    "pagination": {
                        "total": 0,
                        "limit": limit,
                        "offset": offset,
                        "has_more": False,
                    },
                }
            ), 200

        # Count total
        count_row = conn.execute(
            f"""SELECT COUNT(*) as cnt
                FROM pmu_courses c
                WHERE c.date_programme = ? {cond}""",
            (today,),
        ).fetchone()
        total = count_row["cnt"] if count_row else 0

        rows = conn.execute(
            f"""SELECT
                    c.date_programme,
                    c.num_reunion,
                    c.num_course,
                    c.libelle,
                    c.discipline,
                    c.distance,
                    c.hippodrome,
                    c.px_type,
                    COUNT(p.id_cheval) as nb_partants
                FROM pmu_courses c
                LEFT JOIN pmu_partants p
                    ON p.date_programme = c.date_programme
                   AND p.num_reunion    = c.num_reunion
                   AND p.num_course     = c.num_course
                WHERE c.date_programme = ? {cond}
                GROUP BY c.date_programme, c.num_reunion, c.num_course
                ORDER BY c.num_reunion ASC, c.num_course ASC
                LIMIT ? OFFSET ?""",
            (today, limit, offset),
        ).fetchall()

        courses = []
        for r in rows:
            course_id = f"{r['num_reunion']}-{r['num_course']}"
            courses.append(
                {
                    "id": course_id,
                    "date": r["date_programme"],
                    "num_reunion": r["num_reunion"],
                    "num_course": r["num_course"],
                    "libelle": r["libelle"],
                    "discipline": r["discipline"],
                    "distance": r["distance"],
                    "hippodrome": r["hippodrome"],
                    "type_pari": r["px_type"],
                    "nb_partants": r["nb_partants"],
                }
            )

        pagination = paginate_query(courses, total, limit, offset)

        return jsonify(
            {
                "status": "ok",
                "date": today,
                "filter": race_filter,
                "courses": courses,
                **pagination,
            }
        ), 200

    except Exception as e:
        return internal_error(str(e))
    finally:
        conn.close()


# ──────────────────────────────────────────────────────────────
# GET /api/v1/courses/<course_id>/predictions
# course_id format: "{num_reunion}-{num_course}"  e.g. "1-3"
# ──────────────────────────────────────────────────────────────


@courses_bp.route("/<course_id>/predictions", methods=["GET"])
@jwt_required_middleware
@free_daily_limit_check
def course_predictions(course_id):
    """
    Prédictions pour une course
    ---
    tags:
      - Courses
    summary: Prédictions ML pour une course identifiée par {num_reunion}-{num_course}
    security:
      - Bearer: []
    parameters:
      - name: course_id
        in: path
        type: string
        required: true
        description: Identifiant de la course (format num_reunion-num_course, ex "1-3")
      - name: date
        in: query
        type: string
        format: date
        description: Date de la course (YYYY-MM-DD), défaut = aujourd'hui
    responses:
      200:
        description: Prédictions ML pour la course
      400:
        description: Paramètres invalides
      404:
        description: Course introuvable
      429:
        description: Limite quotidienne free tier atteinte
    """
    # Parse course_id
    parts = course_id.split("-")
    if len(parts) != 2:
        return bad_request(
            "course_id doit être au format {num_reunion}-{num_course}, ex: 1-3"
        )

    try:
        num_reunion = int(parts[0])
        num_course = int(parts[1])
    except ValueError:
        return bad_request("num_reunion et num_course doivent être des entiers")

    date_param = request.args.get("date", datetime.now().strftime("%Y-%m-%d"))

    conn = get_db()
    try:
        # Fetch course info
        course_row = conn.execute(
            """SELECT libelle, discipline, distance, hippodrome, px_type
               FROM pmu_courses
               WHERE date_programme = ? AND num_reunion = ? AND num_course = ?""",
            (date_param, num_reunion, num_course),
        ).fetchone()

        if not course_row:
            return not_found(
                f"Course R{num_reunion}C{num_course} introuvable pour le {date_param}"
            )

        # Fetch ML predictions from cache
        preds = []
        if table_exists(conn, "ml_predictions_cache"):
            preds = conn.execute(
                """SELECT horse_name, horse_number, odds, prob_top1, prob_top3,
                          ml_score, recommendation, is_value_bet, risque_label, risque_score
                   FROM ml_predictions_cache
                   WHERE date = ? AND num_reunion = ? AND num_course = ?
                   ORDER BY ml_score DESC""",
                (date_param, num_reunion, num_course),
            ).fetchall()

        # Fetch partants
        partants = conn.execute(
            """SELECT nom, num_pmu, cote_direct, cote_reference, tendance_cote, favoris,
                      tx_victoire, tx_place, forme_recente, driver, entraineur, musique
               FROM pmu_partants
               WHERE date_programme = ? AND num_reunion = ? AND num_course = ?
               ORDER BY num_pmu ASC""",
            (date_param, num_reunion, num_course),
        ).fetchall()

        return jsonify(
            {
                "status": "ok",
                "date": date_param,
                "course": {
                    "id": course_id,
                    "libelle": course_row["libelle"],
                    "discipline": course_row["discipline"],
                    "distance": course_row["distance"],
                    "hippodrome": course_row["hippodrome"],
                    "type_pari": course_row["px_type"],
                },
                "predictions": [dict(p) for p in preds],
                "partants": [dict(p) for p in partants],
            }
        ), 200

    except Exception as e:
        return internal_error(str(e))
    finally:
        conn.close()
