"""Shared state and data models — no app imports to avoid circular deps."""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum


class StepStatus(Enum):
    PENDING = "pending"
    ACTIVE = "active"
    RUNNING = "running"
    SUCCESS = "success"
    FAILED = "failed"
    SKIPPED = "skipped"


@dataclass
class StepInfo:
    number: int
    name: str
    description: str
    status: StepStatus = StepStatus.PENDING


@dataclass
class InstallState:
    """Shared state across all install steps."""

    # Collected config
    api_key: str = ""
    openrouter_key: str = ""
    openai_key: str = ""
    model: str = "minimax-m2.5"
    model_path: str = "openrouter/minimax/minimax-m2.5"
    fallback_path: str = "openrouter/anthropic/claude-haiku-4.5"
    bind: str = "lan"
    channel: str = "none"
    gateway_token: str = ""
    memory_enabled: bool = False

    # Channel-specific
    telegram_token: str = ""
    discord_token: str = ""

    # Runtime info
    vps_ip: str = ""
    os_name: str = ""
    node_version: str = ""
    openclaw_version: str = ""
    use_sudo: bool = False

    # Step tracking
    current_step: int = 1
    steps: list[StepInfo] = field(default_factory=list)
    log_lines: list[str] = field(default_factory=list)

    def __post_init__(self) -> None:
        if not self.steps:
            self.steps = self._default_steps()

    @staticmethod
    def _default_steps() -> list[StepInfo]:
        return [
            StepInfo(1, "Pre-flight", "System checks and requirements"),
            StepInfo(2, "Node.js", "Install or upgrade Node.js v22+"),
            StepInfo(3, "OpenClaw", "Install OpenClaw CLI"),
            StepInfo(4, "Tools", "Install mcporter and clawhub"),
            StepInfo(5, "Config", "Choose model, channel, and options"),
            StepInfo(6, "Token", "Generate gateway auth token"),
            StepInfo(7, "Write Config", "Create openclaw.json"),
            StepInfo(8, "Env Vars", "Set API keys in environment"),
            StepInfo(9, "Workspace", "Create SOUL.md and workspace files"),
            StepInfo(10, "Validate", "Validate configuration"),
            StepInfo(11, "Init Gateway", "First gateway run (auto-init)"),
            StepInfo(12, "Systemd", "Create and start systemd service"),
            StepInfo(13, "MCP", "Connect EasyClaw MCP server"),
            StepInfo(14, "Channel", "Configure messaging channel"),
            StepInfo(15, "Health", "Health checks and summary"),
        ]

    def log(self, msg: str) -> None:
        self.log_lines.append(msg)

    def set_step_status(self, step_num: int, status: StepStatus) -> None:
        for s in self.steps:
            if s.number == step_num:
                s.status = status
                break


MODEL_MAP = {
    "minimax-m2.5": "openrouter/minimax/minimax-m2.5",
    "deepseek-v3.2": "openrouter/deepseek/deepseek-v3.2",
    "claude-haiku-4.5": "openrouter/anthropic/claude-haiku-4.5",
    "claude-sonnet-4.5": "openrouter/anthropic/claude-sonnet-4.5",
    "gpt-4.1-mini": "openrouter/openai/gpt-4.1-mini",
}
