"""TGTC Paper Trading API endpoints."""
from __future__ import annotations

import datetime as dt
import os
from typing import Any

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel

router = APIRouter(prefix="/tgtc", tags=["tgtc-trading"])


def _db_path() -> str:
    from pathlib import Path
    project_root = Path(__file__).parent.parent.parent.parent
    env_path = os.environ.get("TGTC_TRADER_DB", "data/paper/tgtc.db")
    path = Path(env_path) if Path(env_path).is_absolute() else project_root / env_path
    path.parent.mkdir(parents=True, exist_ok=True)
    return str(path)


def _state() -> Any:
    from apps.tgtc_trader.state import TGTCStateManager
    return TGTCStateManager(_db_path())


# ── Request models ────────────────────────────────────────────────────────────

class CreateSessionRequest(BaseModel):
    name: str
    config: str
    capital: float = 10000.0


class AutoStartRequest(BaseModel):
    sessions: list[str] = []
    dry_run: bool = True


class StartNowRequest(BaseModel):
    sessions: list[str] = []
    dry_run: bool = True
    collect_duration_secs: int = 300
    quick_end_after_mins: int = 60


class BacktestRequest(BaseModel):
    date: str                   # YYYY-MM-DD start date
    config: str                 # config path
    universe: str | None = None
    end_date: str | None = None  # YYYY-MM-DD end date (multi-day if set)


# ── Sessions ──────────────────────────────────────────────────────────────────

@router.get("/sessions")
def list_sessions() -> dict[str, Any]:
    state = _state()
    sessions = state.list_sessions()
    today = dt.date.today().isoformat()
    results = []
    for s in sessions:
        daily = state.get_daily_state(s.session_id, today)
        ran_today = daily is not None and daily.phase not in ("idle", "", None)
        equity = state.get_equity(s.session_id) or s.initial_equity
        total_pnl = equity - s.initial_equity
        results.append({
            "session_id": s.session_id,
            "session_name": s.session_name,
            "config_path": s.config_path,
            "initial_equity": s.initial_equity,
            "current_equity": round(equity, 2),
            "total_return_pct": round((total_pnl / s.initial_equity) * 100, 2) if s.initial_equity > 0 else 0.0,
            "created_at": s.created_at,
            "status": s.status,
            "ran_today": ran_today,
            "phase": daily.phase if daily else "idle",
        })
    return {"sessions": results}


@router.post("/sessions")
def create_session(req: CreateSessionRequest) -> dict[str, Any]:
    from pathlib import Path
    import yaml

    project_root = Path(__file__).parent.parent.parent.parent
    config_path = req.config if Path(req.config).is_absolute() else str(project_root / req.config)
    if not Path(config_path).exists():
        raise HTTPException(status_code=404, detail=f"Config not found: {config_path}")

    try:
        raw = yaml.safe_load(Path(config_path).read_text()) or {}
        if raw.get("strategy_mode") != "tgtc":
            raise HTTPException(
                status_code=400,
                detail=f"Config strategy_mode must be 'tgtc', got '{raw.get('strategy_mode')}'"
            )
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Invalid config: {e}")

    state = _state()
    if state.get_session(req.name) is not None:
        raise HTTPException(status_code=409, detail=f"Session '{req.name}' already exists")

    session_id = state.create_session(req.name, config_path, req.capital)
    return {"session_id": session_id, "session_name": req.name,
            "config_path": config_path, "initial_equity": req.capital}


@router.get("/sessions/{session_id}")
def get_session(session_id: str) -> dict[str, Any]:
    state = _state()
    session = state.get_session(session_id)
    if session is None:
        raise HTTPException(status_code=404, detail="Session not found")
    equity = state.get_equity(session.session_id) or session.initial_equity
    return {
        "session_id": session.session_id,
        "session_name": session.session_name,
        "config_path": session.config_path,
        "initial_equity": session.initial_equity,
        "current_equity": round(equity, 2),
        "created_at": session.created_at,
        "status": session.status,
    }


@router.delete("/sessions/{session_id}")
def delete_session(session_id: str) -> dict[str, Any]:
    state = _state()
    session = state.get_session(session_id)
    if session is None:
        raise HTTPException(status_code=404, detail="Session not found")
    state.delete_session(session_id)
    return {"deleted": session_id}


# ── Strategies list ───────────────────────────────────────────────────────────

@router.get("/strategies")
def list_strategies() -> dict[str, Any]:
    """List available TGTC strategy configs."""
    import yaml
    from pathlib import Path

    project_root = Path(__file__).parent.parent.parent.parent
    strat_dir = project_root / "configs" / "intraday" / "strategies"
    strategies = []
    for p in sorted(strat_dir.glob("tgtc_*.yaml")):
        try:
            raw = yaml.safe_load(p.read_text()) or {}
            if raw.get("strategy_mode") != "tgtc":
                continue
            meta = raw.get("_meta", {})
            strategies.append({
                "config_path": str(p.relative_to(project_root)),
                "name": meta.get("name", p.stem),
                "id": meta.get("id", p.stem),
                "status": meta.get("status", ""),
                "live_readiness": meta.get("live_readiness", ""),
                "description": meta.get("description", ""),
            })
        except Exception:
            pass
    return {"strategies": strategies}


# ── Live data ─────────────────────────────────────────────────────────────────

@router.get("/sessions/{session_id}/snapshots")
def get_snapshots(session_id: str, date: str | None = None) -> dict[str, Any]:
    state = _state()
    if state.get_session(session_id) is None:
        raise HTTPException(status_code=404, detail="Session not found")
    d = date or dt.date.today().isoformat()
    rows = state.get_latest_snapshots(session_id, d)
    return {"date": d, "snapshots": rows, "count": len(rows)}


@router.get("/sessions/{session_id}/candidates")
def get_candidates(session_id: str, date: str | None = None) -> dict[str, Any]:
    state = _state()
    if state.get_session(session_id) is None:
        raise HTTPException(status_code=404, detail="Session not found")
    d = date or dt.date.today().isoformat()
    return {"date": d, "candidates": state.get_candidates(session_id, d)}


@router.get("/sessions/{session_id}/positions")
def get_positions(session_id: str) -> dict[str, Any]:
    state = _state()
    if state.get_session(session_id) is None:
        raise HTTPException(status_code=404, detail="Session not found")
    positions = state.get_all_positions(session_id)
    return {"positions": positions}


@router.get("/sessions/{session_id}/trades")
def get_trades(session_id: str) -> dict[str, Any]:
    state = _state()
    if state.get_session(session_id) is None:
        raise HTTPException(status_code=404, detail="Session not found")
    return {"trades": state.get_trades(session_id)}


@router.get("/sessions/{session_id}/equity")
def get_equity(session_id: str) -> dict[str, Any]:
    state = _state()
    session = state.get_session(session_id)
    if session is None:
        raise HTTPException(status_code=404, detail="Session not found")
    snapshots = state.get_daily_snapshots(session_id)
    return {
        "initial_equity": session.initial_equity,
        "current_equity": state.get_equity(session_id) or session.initial_equity,
        "daily_snapshots": snapshots,
    }


# ── Auto scheduler ────────────────────────────────────────────────────────────

@router.get("/auto")
def get_auto_status() -> dict[str, Any]:
    from apps.web.tgtc_service import tgtc_auto_scheduler
    status = tgtc_auto_scheduler.get_status()
    log_text = tgtc_auto_scheduler.get_log(lines=200)
    return {**status, "log": log_text, "log_lines": log_text.splitlines()[-50:]}


@router.post("/auto/start")
async def start_auto(req: AutoStartRequest) -> dict[str, Any]:
    from apps.web.tgtc_service import tgtc_auto_scheduler
    if tgtc_auto_scheduler.running:
        raise HTTPException(status_code=409, detail="TGTC scheduler already running")
    try:
        tgtc_auto_scheduler.start(
            sessions=req.sessions,
            db_path=_db_path(),
            dry_run=req.dry_run,
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    return {"started": True, "dry_run": req.dry_run}


@router.post("/auto/start-now")
async def start_auto_now(req: StartNowRequest) -> dict[str, Any]:
    from apps.web.tgtc_service import tgtc_auto_scheduler
    if tgtc_auto_scheduler.running:
        raise HTTPException(status_code=409, detail="TGTC scheduler already running")
    try:
        tgtc_auto_scheduler.start(
            sessions=req.sessions,
            db_path=_db_path(),
            dry_run=req.dry_run,
            start_now=True,
            collect_duration_secs=req.collect_duration_secs,
            quick_end_after_mins=req.quick_end_after_mins,
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    return {
        "started_now": True,
        "dry_run": req.dry_run,
        "collect_duration_secs": req.collect_duration_secs,
        "quick_end_after_mins": req.quick_end_after_mins,
    }


@router.post("/auto/stop")
def stop_auto() -> dict[str, Any]:
    from apps.web.tgtc_service import tgtc_auto_scheduler
    tgtc_auto_scheduler.stop()
    return {"stopped": True}


@router.post("/auto/clear-log")
def clear_auto_log() -> dict[str, Any]:
    from apps.web.tgtc_service import tgtc_auto_scheduler
    tgtc_auto_scheduler.clear_log()
    return {"cleared": True}


# ── Backtest ──────────────────────────────────────────────────────────────────

@router.post("/backtest/submit")
async def submit_backtest(req: BacktestRequest) -> dict[str, Any]:
    from pathlib import Path

    project_root = Path(__file__).parent.parent.parent.parent
    config_path = req.config if Path(req.config).is_absolute() else str(project_root / req.config)
    if not Path(config_path).exists():
        raise HTTPException(status_code=404, detail=f"Config not found: {config_path}")

    try:
        dt.date.fromisoformat(req.date)
        if req.end_date:
            end = dt.date.fromisoformat(req.end_date)
            if end < dt.date.fromisoformat(req.date):
                raise HTTPException(status_code=400, detail="end_date must be >= date")
    except HTTPException:
        raise
    except ValueError as e:
        raise HTTPException(status_code=400, detail=f"Invalid date format: {e}")

    from apps.web.tgtc_service import submit_backtest as _submit
    task_id = await _submit(req.date, config_path, req.universe, req.end_date)
    return {"task_id": task_id, "status": "pending"}


@router.get("/backtest/tasks")
def list_backtest_tasks() -> dict[str, Any]:
    from apps.web.tgtc_service import get_bt_tasks
    return {"tasks": get_bt_tasks()}


@router.get("/backtest/tasks/{task_id}")
def get_backtest_task(task_id: str) -> dict[str, Any]:
    from apps.web.tgtc_service import get_bt_task
    task = get_bt_task(task_id)
    if task is None:
        raise HTTPException(status_code=404, detail="Task not found")
    return task


@router.get("/backtest/tasks/{task_id}/result")
def get_backtest_result(task_id: str) -> dict[str, Any]:
    from apps.web.tgtc_service import get_bt_task
    task = get_bt_task(task_id)
    if task is None:
        raise HTTPException(status_code=404, detail="Task not found")
    if task["status"] != "completed":
        raise HTTPException(status_code=409, detail=f"Task status: {task['status']}")
    return task.get("result") or {}
