"""Profile data models for per-game/app optimization."""
from __future__ import annotations

from typing import Optional
from pydantic import BaseModel, Field


class PowerProfile(BaseModel):
    """Power-related settings for a profile."""
    cpu_governor: Optional[str] = None          # Linux: performance, powersave, etc.
    gpu_perf_level: Optional[str] = None        # Linux AMD: auto, high, profile_peak
    gpu_power_profile: Optional[int] = None     # Linux AMD: 0=default, 1=3D_FULL_SCREEN
    nvidia_perf_mode: Optional[bool] = None     # Enable max clocks
    timer_resolution_ms: Optional[float] = None # Windows: 0.5, 1.0


class NetworkProfile(BaseModel):
    """Network tuning for a profile."""
    tcp_nodelay: Optional[bool] = None
    tcp_low_latency: Optional[bool] = None     # Linux
    congestion_control: Optional[str] = None   # Linux: bbr, cubic
    interrupt_coalescing: Optional[bool] = None


class ProcessProfile(BaseModel):
    """Process scheduling for a profile."""
    priority: Optional[str] = None             # high, above_normal, realtime
    nice: Optional[int] = None                 # Linux: -20 to 19
    io_class: Optional[str] = None             # Linux: realtime, best-effort, idle
    affinity_cores: Optional[list[int]] = None # Pin to specific cores
    throttle_background: bool = False          # Lower bg process priority


class GPUProfile(BaseModel):
    """GPU-specific settings."""
    vsync: Optional[bool] = None
    max_fps: Optional[int] = None
    shader_cache: Optional[bool] = None
    anti_lag: Optional[bool] = None            # AMD
    reflex: Optional[bool] = None              # NVIDIA


class GameProfile(BaseModel):
    """Complete optimization profile for a game or application."""
    name: str
    exe_names: list[str] = Field(default_factory=list)
    genre: str = "unknown"
    publisher: str = "unknown"
    tier: str = "gamer"                        # Minimum tier required

    power: PowerProfile = Field(default_factory=PowerProfile)
    network: NetworkProfile = Field(default_factory=NetworkProfile)
    process: ProcessProfile = Field(default_factory=ProcessProfile)
    gpu: GPUProfile = Field(default_factory=GPUProfile)

    # Launch options
    env_vars: dict[str, str] = Field(default_factory=dict)
    pre_launch: list[str] = Field(default_factory=list)   # Commands to run before
    post_exit: list[str] = Field(default_factory=list)     # Commands to run after


# ── Built-in Profiles ────────────────────────────────────────────────────

BUILTIN_PROFILES: dict[str, GameProfile] = {
    # ── FPS / Competitive (latency-critical) ──
    "valorant": GameProfile(
        name="Valorant",
        exe_names=["valorant.exe"],
        genre="fps", publisher="Riot Games",
        power=PowerProfile(
            gpu_perf_level="profile_peak", gpu_power_profile=1,
            nvidia_perf_mode=True, timer_resolution_ms=0.5,
        ),
        network=NetworkProfile(
            tcp_nodelay=True, tcp_low_latency=True,
            interrupt_coalescing=False,
        ),
        process=ProcessProfile(
            priority="high", nice=-15, io_class="realtime",
            throttle_background=True,
        ),
        gpu=GPUProfile(vsync=False, anti_lag=True, reflex=True),
    ),
    "cs2": GameProfile(
        name="Counter-Strike 2",
        exe_names=["cs2.exe", "cs2"],
        genre="fps", publisher="Valve",
        power=PowerProfile(
            gpu_perf_level="profile_peak", gpu_power_profile=1,
            nvidia_perf_mode=True, timer_resolution_ms=0.5,
        ),
        network=NetworkProfile(
            tcp_nodelay=True, tcp_low_latency=True,
            congestion_control="bbr", interrupt_coalescing=False,
        ),
        process=ProcessProfile(
            priority="high", nice=-15, io_class="realtime",
            throttle_background=True,
        ),
        gpu=GPUProfile(vsync=False, anti_lag=True, reflex=True),
        env_vars={"DXVK_ASYNC": "1"},  # Proton async shader compile
    ),
    "apex": GameProfile(
        name="Apex Legends",
        exe_names=["r5apex.exe"],
        genre="fps", publisher="Respawn",
        power=PowerProfile(
            gpu_perf_level="profile_peak", gpu_power_profile=1,
            nvidia_perf_mode=True, timer_resolution_ms=0.5,
        ),
        network=NetworkProfile(
            tcp_nodelay=True, tcp_low_latency=True,
            interrupt_coalescing=False,
        ),
        process=ProcessProfile(
            priority="high", nice=-10, throttle_background=True,
        ),
        gpu=GPUProfile(vsync=False, anti_lag=True),
    ),
    "fortnite": GameProfile(
        name="Fortnite",
        exe_names=["fortniteclient-win64-shipping.exe"],
        genre="fps", publisher="Epic Games",
        power=PowerProfile(
            gpu_perf_level="profile_peak", nvidia_perf_mode=True,
            timer_resolution_ms=0.5,
        ),
        network=NetworkProfile(tcp_nodelay=True, tcp_low_latency=True),
        process=ProcessProfile(priority="high", nice=-10, throttle_background=True),
        gpu=GPUProfile(vsync=False),
    ),

    # ── MOBA (network-critical) ──
    "league": GameProfile(
        name="League of Legends",
        exe_names=["league of legends.exe"],
        genre="moba", publisher="Riot Games",
        network=NetworkProfile(
            tcp_nodelay=True, tcp_low_latency=True,
            congestion_control="bbr",
        ),
        process=ProcessProfile(priority="above_normal", nice=-5),
        gpu=GPUProfile(vsync=False),
    ),
    "dota2": GameProfile(
        name="Dota 2",
        exe_names=["dota2.exe", "dota2"],
        genre="moba", publisher="Valve",
        network=NetworkProfile(
            tcp_nodelay=True, tcp_low_latency=True,
            congestion_control="bbr",
        ),
        process=ProcessProfile(priority="above_normal", nice=-5),
        env_vars={"DXVK_ASYNC": "1"},
    ),

    # ── RPG / Open World (GPU-heavy) ──
    "cyberpunk": GameProfile(
        name="Cyberpunk 2077",
        exe_names=["cyberpunk2077.exe"],
        genre="rpg", publisher="CDPR", tier="pro",
        power=PowerProfile(
            gpu_perf_level="profile_peak", gpu_power_profile=1,
            nvidia_perf_mode=True,
        ),
        process=ProcessProfile(
            priority="high", nice=-10, throttle_background=True,
        ),
        gpu=GPUProfile(shader_cache=True, reflex=True),
    ),
    "elden_ring": GameProfile(
        name="Elden Ring",
        exe_names=["eldenring.exe"],
        genre="rpg", publisher="FromSoftware", tier="pro",
        power=PowerProfile(
            gpu_perf_level="profile_peak", nvidia_perf_mode=True,
        ),
        process=ProcessProfile(priority="high", nice=-10, throttle_background=True),
        gpu=GPUProfile(vsync=False, shader_cache=True),
    ),

    # ── MMO (network + GPU) ──
    "ffxiv": GameProfile(
        name="Final Fantasy XIV",
        exe_names=["ffxiv_dx11.exe"],
        genre="mmo", publisher="Square Enix",
        network=NetworkProfile(tcp_nodelay=True, tcp_low_latency=True),
        process=ProcessProfile(priority="above_normal", nice=-5),
        gpu=GPUProfile(shader_cache=True),
    ),
    "wow": GameProfile(
        name="World of Warcraft",
        exe_names=["wow.exe"],
        genre="mmo", publisher="Blizzard",
        network=NetworkProfile(tcp_nodelay=True, tcp_low_latency=True),
        process=ProcessProfile(priority="above_normal", nice=-5),
    ),

    # ── Survival (balanced) ──
    "rust": GameProfile(
        name="Rust",
        exe_names=["rustclient.exe", "RustClient"],
        genre="survival", publisher="Facepunch",
        power=PowerProfile(gpu_perf_level="profile_peak", nvidia_perf_mode=True),
        network=NetworkProfile(tcp_nodelay=True, tcp_low_latency=True),
        process=ProcessProfile(priority="high", nice=-10, throttle_background=True),
        gpu=GPUProfile(shader_cache=True),
    ),
    "valheim": GameProfile(
        name="Valheim",
        exe_names=["valheim.x86_64", "valheim.exe"],
        genre="survival", publisher="Iron Gate",
        power=PowerProfile(gpu_perf_level="high"),
        process=ProcessProfile(priority="above_normal", nice=-5),
    ),

    # ── Racing / Sim (latency-critical) ──
    "iracing": GameProfile(
        name="iRacing",
        exe_names=["iracing.exe"],
        genre="racing", publisher="iRacing", tier="pro",
        power=PowerProfile(
            gpu_perf_level="profile_peak", nvidia_perf_mode=True,
            timer_resolution_ms=0.5,
        ),
        network=NetworkProfile(
            tcp_nodelay=True, interrupt_coalescing=False,
        ),
        process=ProcessProfile(
            priority="high", nice=-15, io_class="realtime",
            throttle_background=True,
        ),
        gpu=GPUProfile(vsync=False),
    ),

    # ── Streaming ──
    "obs": GameProfile(
        name="OBS Studio",
        exe_names=["obs64.exe", "obs", "obs-studio"],
        genre="streaming", publisher="OBS Project",
        power=PowerProfile(gpu_perf_level="high"),
        process=ProcessProfile(priority="above_normal", nice=-5),
        gpu=GPUProfile(shader_cache=True),
    ),

    # ── Generic profiles by genre ──
    "_fps_default": GameProfile(
        name="FPS Default",
        exe_names=[],
        genre="fps",
        power=PowerProfile(
            gpu_perf_level="profile_peak", gpu_power_profile=1,
            nvidia_perf_mode=True, timer_resolution_ms=0.5,
        ),
        network=NetworkProfile(
            tcp_nodelay=True, tcp_low_latency=True,
            interrupt_coalescing=False,
        ),
        process=ProcessProfile(
            priority="high", nice=-10, throttle_background=True,
        ),
        gpu=GPUProfile(vsync=False, anti_lag=True, reflex=True),
    ),
    "_rpg_default": GameProfile(
        name="RPG Default",
        exe_names=[],
        genre="rpg",
        power=PowerProfile(gpu_perf_level="profile_peak", nvidia_perf_mode=True),
        process=ProcessProfile(priority="above_normal", nice=-5, throttle_background=True),
        gpu=GPUProfile(shader_cache=True),
    ),
    "_mmo_default": GameProfile(
        name="MMO Default",
        exe_names=[],
        genre="mmo",
        network=NetworkProfile(tcp_nodelay=True, tcp_low_latency=True),
        process=ProcessProfile(priority="above_normal", nice=-5),
    ),
}
