#!/usr/bin/env python3
"""
Backtest route for API v1.

GET /api/v1/backtest  — Résultats backtest historiques (pro)
"""

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

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

backtest_bp = Blueprint("v1_backtest", __name__, url_prefix="/api/v1")


@backtest_bp.route("/backtest", methods=["GET"])
@jwt_required_middleware
@plan_required("pro")
def backtest():
    """
    Backtest historique
    ---
    tags:
      - Backtest
    summary: Résultats backtest historiques des paris simulés — accès pro uniquement
    security:
      - Bearer: []
    parameters:
      - name: start
        in: query
        type: string
        format: date
        description: Date de début (YYYY-MM-DD), défaut = -30j
      - name: end
        in: query
        type: string
        format: date
        description: Date de fin (YYYY-MM-DD), défaut = aujourd'hui
      - name: limit
        in: query
        type: integer
        default: 50
      - name: offset
        in: query
        type: integer
        default: 0
    responses:
      200:
        description: Résultats backtest
      401:
        description: Token invalide
      403:
        description: Plan insuffisant (pro requis)
    """
    start = request.args.get("start")
    end = request.args.get("end")

    # Validate date formats
    for label, val in [("start", start), ("end", end)]:
        if val:
            try:
                datetime.strptime(val, "%Y-%m-%d")
            except ValueError:
                return bad_request(
                    f"Paramètre '{label}' invalide, format attendu: YYYY-MM-DD"
                )

    if not start:
        start = (datetime.now() - timedelta(days=30)).strftime("%Y-%m-%d")
    if not end:
        end = datetime.now().strftime("%Y-%m-%d")

    limit, offset = get_pagination_params(default_limit=50, max_limit=200)

    conn = get_db()
    try:
        if not table_exists(conn, "bet_results"):
            return jsonify(
                {
                    "status": "ok",
                    "period": {"start": start, "end": end},
                    "summary": {
                        "total_bets": 0,
                        "message": "Aucune donnée bet_results",
                    },
                    "by_type": {},
                    "details": [],
                    "pagination": {
                        "total": 0,
                        "limit": limit,
                        "offset": offset,
                        "has_more": False,
                    },
                }
            ), 200

        # Summary
        summary_row = conn.execute(
            """SELECT
                   COUNT(*)                                          AS total,
                   SUM(CASE WHEN resultat='GAGNE' THEN 1 ELSE 0 END) AS gagne,
                   SUM(mise)                                         AS mise,
                   SUM(gain)                                         AS gain
               FROM bet_results
               WHERE date BETWEEN ? AND ?""",
            (start, end),
        ).fetchone()

        total_bets = summary_row["total"] or 0
        gagne = summary_row["gagne"] or 0
        mise = float(summary_row["mise"] or 0)
        gain = float(summary_row["gain"] or 0)
        roi = round((gain - mise) / mise * 100, 1) if mise > 0 else 0.0
        precision = round(gagne / total_bets * 100, 1) if total_bets > 0 else 0.0

        # By type
        by_type_rows = conn.execute(
            """SELECT
                   type_pari,
                   COUNT(*)                                          AS total,
                   SUM(CASE WHEN resultat='GAGNE' THEN 1 ELSE 0 END) AS gagne,
                   SUM(mise)                                         AS mise,
                   SUM(gain)                                         AS gain
               FROM bet_results
               WHERE date BETWEEN ? AND ?
               GROUP BY type_pari""",
            (start, end),
        ).fetchall()

        by_type = {}
        for row in by_type_rows:
            t = row["total"] or 0
            g = row["gagne"] or 0
            m = float(row["mise"] or 0)
            gn = float(row["gain"] or 0)
            by_type[row["type_pari"]] = {
                "count": t,
                "gagne": g,
                "mise": round(m, 2),
                "gain": round(gn, 2),
                "roi": round((gn - m) / m * 100, 1) if m > 0 else 0.0,
                "precision": round(g / t * 100, 1) if t > 0 else 0.0,
            }

        # Paginated details
        count_row = conn.execute(
            "SELECT COUNT(*) AS cnt FROM bet_results WHERE date BETWEEN ? AND ?",
            (start, end),
        ).fetchone()
        detail_total = count_row["cnt"] if count_row else 0

        detail_rows = conn.execute(
            """SELECT date, race_name, type_pari, horse_name, horse_number,
                      COALESCE(cote, 0) AS cote, mise, resultat, gain
               FROM bet_results
               WHERE date BETWEEN ? AND ?
               ORDER BY date DESC, id DESC
               LIMIT ? OFFSET ?""",
            (start, end, limit, offset),
        ).fetchall()

        details = [dict(r) for r in detail_rows]
        pagination = paginate_query(details, detail_total, limit, offset)

        return jsonify(
            {
                "status": "ok",
                "period": {"start": start, "end": end},
                "summary": {
                    "total_bets": total_bets,
                    "gagne": gagne,
                    "perdu": total_bets - gagne,
                    "precision": precision,
                    "mise_totale": round(mise, 2),
                    "gain_total": round(gain, 2),
                    "roi": roi,
                },
                "by_type": by_type,
                "details": details,
                **pagination,
            }
        ), 200

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