"""Data transformation for API responses."""
import json
from datetime import datetime
from typing import Optional

from .. import db
from ..config import (
    get_player_name,
    get_display_columns,
    set_display_columns,
    AVAILABLE_COLUMNS,
    load_config,
    save_config,
    clear_config_cache,
)
from ..ui import calculate_summary


def get_mmr_history(
    limit: int = 100,
    days: Optional[int] = None,
    matchup: Optional[str] = None,
    result: Optional[str] = None,
    player_race: Optional[str] = None,
    is_ladder: Optional[bool] = True,
) -> dict:
    """Get MMR history for graphing.

    Args:
        limit: Maximum number of games to return
        days: Filter to last N days
        matchup: Filter by matchup
        result: Filter by result
        player_race: Filter by player race
        is_ladder: Filter to ladder games (default True)

    Returns:
        Dict with player_name, data (list of mmr entries, oldest first), and tags
    """
    replays = db.get_replays(
        limit=limit,
        days=days,
        matchup=matchup,
        result=result,
        player_race=player_race,
        is_ladder=is_ladder,
    )
    data = [
        {
            "date": r["played_at"],
            "mmr": r["player_mmr"],
            "result": r["result"],
            "matchup": r["matchup"],
        }
        for r in reversed(replays)  # Oldest first for graph
        if r.get("player_mmr")
    ]

    tags = _format_tags(db.get_tags())

    return {
        "player_name": get_player_name(),
        "data": data,
        "tags": tags,
    }


def get_replays_api(
    matchup: Optional[str] = None,
    result: Optional[str] = None,
    map_name: Optional[str] = None,
    days: Optional[int] = None,
    limit: Optional[int] = None,
    min_length: Optional[int] = None,
    max_length: Optional[int] = None,
    min_workers_8m: Optional[int] = None,
    max_workers_8m: Optional[int] = None,
    player_race: Optional[str] = None,
    is_ladder: Optional[bool] = None,
) -> dict:
    """Get replays with optional filters, plus summary stats.

    Returns:
        Dict with replays list, summary stats, and total count
    """
    replays = db.get_replays(
        matchup=matchup,
        result=result,
        map_name=map_name,
        days=days,
        limit=limit,
        min_length=min_length,
        max_length=max_length,
        min_workers_8m=min_workers_8m,
        max_workers_8m=max_workers_8m,
        player_race=player_race,
        is_ladder=is_ladder,
    )

    summary = calculate_summary(replays)

    return {
        "replays": replays,
        "summary": summary,
        "total": len(replays),
    }


def get_latest_api() -> dict:
    """Get the most recent replay."""
    replay = db.get_latest_replay()
    return {"replay": replay}


def get_stats_api(
    matchup: Optional[str] = None,
    days: Optional[int] = None,
    player_race: Optional[str] = None,
    is_ladder: Optional[bool] = None,
) -> dict:
    """Get aggregate stats and per-matchup breakdown."""
    stats = db.get_stats(
        matchup=matchup, days=days,
        player_race=player_race, is_ladder=is_ladder,
    )
    matchup_stats = db.get_stats_by_matchup(
        days=days, player_race=player_race, is_ladder=is_ladder,
    ) if not matchup else []

    return {
        "stats": stats,
        "matchup_stats": matchup_stats,
    }


def get_maps_api() -> dict:
    """Get unique map names."""
    maps = db.get_unique_map_names()
    return {"maps": maps}


def get_tags_api() -> dict:
    """Get all tags with type classification."""
    tags = _format_tags(db.get_tags())
    return {"tags": tags}


def create_tag_api(label: str, date: Optional[str] = None, end_date: Optional[str] = None) -> dict:
    """Create a new tag."""
    tag_date = date or datetime.now().strftime("%Y-%m-%d")
    success = db.add_tag(tag_date, label, end_date=end_date)

    if success:
        return {"success": True, "message": f"Tag '{label}' created"}
    return {"success": False, "message": f"Tag already exists: {label} on {tag_date}"}


def end_tag_api(tag_id: int, end_date: Optional[str] = None) -> dict:
    """End an ongoing tag by finding it by ID."""
    date = end_date or datetime.now().strftime("%Y-%m-%d")

    all_tags = db.get_tags()
    tag = next((t for t in all_tags if t["id"] == tag_id), None)

    if not tag:
        return {"success": False, "message": f"Tag not found: {tag_id}"}

    success = db.end_tag(tag["label"], date)
    if success:
        return {"success": True, "message": f"Tag '{tag['label']}' ended on {date}"}
    return {"success": False, "message": f"No ongoing tag found: {tag['label']}"}


def delete_tag_api(tag_id: int) -> dict:
    """Delete a tag by ID."""
    all_tags = db.get_tags()
    tag = next((t for t in all_tags if t["id"] == tag_id), None)

    if not tag:
        return {"success": False, "message": f"Tag not found: {tag_id}"}

    count = db.remove_tag(tag["tag_date"], tag["label"])
    if count > 0:
        return {"success": True, "message": f"Tag '{tag['label']}' deleted"}
    return {"success": False, "message": f"Failed to delete tag: {tag_id}"}


def get_columns_api() -> dict:
    """Get current display columns and available columns."""
    current = get_display_columns()
    available = {
        key: {"header": header, "width": width, "justify": justify}
        for key, (header, width, justify) in AVAILABLE_COLUMNS.items()
    }

    return {
        "current": current,
        "available": available,
    }


def update_columns_api(columns: list) -> dict:
    """Update display columns."""
    invalid = [c for c in columns if c not in AVAILABLE_COLUMNS]
    if invalid:
        return {"success": False, "message": f"Invalid columns: {', '.join(invalid)}"}

    set_display_columns(columns)
    return {"success": True, "columns": columns}


def trigger_scan_api() -> dict:
    """Trigger a replay scan."""
    from ..cli import auto_scan

    new_count = auto_scan(silent=True)
    return {"new_replays": new_count}


def get_config_api() -> dict:
    """Get current configuration info."""
    config = load_config()

    return {
        "player_name": config["player_name"],
        "region": config.get("region", ""),
        "benchmarks": config["benchmarks"],
        "server": config["server"],
        "auto_scan_interval_ms": config.get("auto_scan_interval_ms", 2000),
    }


def update_config_api(player_name: Optional[str] = None, region: Optional[str] = None) -> dict:
    """Update configuration (player name and/or region)."""
    config = load_config()

    if player_name is not None:
        config["player_name"] = player_name
    if region is not None:
        config["region"] = region

    save_config(config)
    clear_config_cache()
    return {"success": True}


def get_races_api() -> dict:
    """Get race distribution and auto-detected default race."""
    distribution = db.get_race_distribution()
    default_race = db.get_most_played_race()

    return {
        "races": distribution,
        "default": default_race,
    }


# ============================================================
# REPLAY NOTES
# ============================================================


def get_notes_api(replay_id: str) -> dict:
    """Get analysis notes for a replay."""
    notes = db.get_replay_notes(replay_id)
    if notes and notes.get("analysis_json"):
        notes["analysis"] = json.loads(notes["analysis_json"])
    return {"notes": notes}


def save_notes_api(replay_id: str, analysis: dict) -> dict:
    """Save analysis notes for a replay."""
    analysis_json = json.dumps(analysis)
    success = db.save_replay_notes(replay_id, analysis_json)
    if success:
        return {"success": True, "message": "Analysis saved"}
    return {"success": False, "message": "Failed to save analysis"}


def delete_notes_api(replay_id: str) -> dict:
    """Delete analysis notes for a replay."""
    success = db.delete_replay_notes(replay_id)
    if success:
        return {"success": True, "message": "Analysis deleted"}
    return {"success": False, "message": "No analysis found"}


def get_notes_feed_api(days: Optional[int] = None, limit: Optional[int] = None) -> dict:
    """Get all notes with replay context for feed view."""
    notes = db.get_all_notes(days=days, limit=limit)
    # Parse JSON for each note
    for note in notes:
        if note.get("analysis_json"):
            note["analysis"] = json.loads(note["analysis_json"])
    return {"notes": notes}


def get_analysis_config_api() -> dict:
    """Get post-game analysis form field configuration."""
    config = load_config()
    fields = config.get("post_game_analysis", {}).get("fields", [])
    return {"fields": fields}


# ============================================================
# INTERNAL HELPERS
# ============================================================


def _format_tags(raw_tags: list) -> list:
    """Format raw tag dicts with type classification."""
    tags = []
    for tag in raw_tags:
        start_date = tag["tag_date"]
        end_date = tag.get("end_date")

        if end_date is None:
            tag_type = "ongoing"
        elif end_date == start_date:
            tag_type = "single"
        else:
            tag_type = "range"

        tags.append({
            "id": tag["id"],
            "label": tag["label"],
            "start_date": start_date,
            "end_date": end_date,
            "type": tag_type,
        })

    return tags
