from __future__ import annotations

import asyncio
import time
import uuid
from typing import Any, Optional

STEPS = [
    ("step-01-input-ingestion",    "Input Ingestion"),
    ("step-02-prd-generation",     "PRD + DDL Generation"),
    ("step-02c-dalfin",            "Mantara Schema + Dalfin"),
    ("step-07-save-ddl-to-db",     "DDL → Database"),
    ("step-03-backend-generation", "Backend / API Generation"),
    ("step-04-ir-generation",      "IR Generation"),
    ("step-05-react-generation",   "React Generation"),
]
STEP_SEQUENCE = [s[0] for s in STEPS]


def _fresh_pipeline(run_id: Optional[str] = None) -> dict:
    return {
        "run_id": run_id,
        "steps": {
            key: {
                "status": "pending",
                "duration_ms": None,
                "start_time": None,
                "input_tokens": 0,
                "output_tokens": 0,
                "total_tokens": 0,
                "llm_calls": 0,
                "llm_details": [],
                "retries": 0,
                "notes": {},
                "sub_steps": [],
            }
            for key, _ in STEPS
        },
        "current_step": None,
        "logs": [],
        "project_root": None,
        "artifacts": {
            "ddl": None,
            "prd": False,
            "cir": False,
            "system_name": None,
            "api_endpoints": None,
            "api_modules": [],
            "ir_pages": [],
            "react_pages": [],
            "mantara_done": False,
            "ddl_to_db": None,
        },
        "totals": {"input_tokens": 0, "output_tokens": 0, "total_tokens": 0, "llm_calls": 0},
        "current_llm": None,
        "log_path": None,
    }


class SessionState:
    def __init__(self, session_id: str):
        self.session_id = session_id
        self.runner: Any = None
        self.status: str = "idle"
        self.pipeline: dict = _fresh_pipeline()
        self._started: set = set()

        self.scripts_runner: Any = None
        self.scripts_status: str = "idle"
        self.scripts_dest: Optional[str] = None
        self.scripts_logs: list[str] = []

        self.gitlab_runner: Any = None
        self.gitlab_status: str = "idle"
        self.gitlab_url: Optional[str] = None
        self.gitlab_logs: list[str] = []

        self.efs_runner: Any = None
        self.efs_status: str = "idle"
        self.efs_logs: list[str] = []
        self.efs_dest: Optional[str] = None

        self.tenant_runner: Any = None
        self.tenant_status: str = "idle"
        self.tenant_result: Optional[str] = None
        self.tenant_logs: list[str] = []

        self.jenkins_runner: Any = None
        self.jenkins_status: str = "idle"
        self.jenkins_url: Optional[str] = None
        self.jenkins_logs: list[str] = []

        self.jenkins_trig_runner: Any = None
        self.jenkins_trig_status: str = "idle"
        self.jenkins_trig_url: Optional[str] = None
        self.jenkins_trig_logs: list[str] = []

        self.pr_runner: Any = None
        self.pr_status: str = "idle"
        self.pr_url: Optional[str] = None
        self.pr_logs: list[str] = []

        self.pr_trig_runner: Any = None
        self.pr_trig_status: str = "idle"
        self.pr_trig_url: Optional[str] = None
        self.pr_trig_logs: list[str] = []

        self.db_runner: Any = None
        self.db_status: str = "idle"
        self.db_logs: list[str] = []

        self.setup_runner: Any = None
        self.setup_status: str = "idle"
        self.setup_logs: list[str] = []

        self.build_runner: Any = None
        self.build_status: str = "idle"
        self.build_logs: list[str] = []

        self.last_active: float = time.time()

    def reset_pipeline(self, run_id: Optional[str] = None) -> None:
        self.pipeline = _fresh_pipeline(run_id)
        self._started = set()

    def to_dict(self) -> dict:
        return {
            "session_id": self.session_id,
            "status": self.status,
            "pipeline": self.pipeline,
            "scripts_status": self.scripts_status,
            "scripts_dest": self.scripts_dest,
            "scripts_logs": self.scripts_logs[-100:],
            "gitlab_status": self.gitlab_status,
            "gitlab_url": self.gitlab_url,
            "gitlab_logs": self.gitlab_logs[-100:],
            "efs_status": self.efs_status,
            "efs_dest": self.efs_dest,
            "efs_logs": self.efs_logs[-100:],
            "tenant_status": self.tenant_status,
            "tenant_result": self.tenant_result,
            "tenant_logs": self.tenant_logs[-100:],
            "jenkins_status": self.jenkins_status,
            "jenkins_url": self.jenkins_url,
            "jenkins_logs": self.jenkins_logs[-100:],
            "jenkins_trig_status": self.jenkins_trig_status,
            "jenkins_trig_url": self.jenkins_trig_url,
            "jenkins_trig_logs": self.jenkins_trig_logs[-100:],
            "pr_status": self.pr_status,
            "pr_url": self.pr_url,
            "pr_logs": self.pr_logs[-100:],
            "pr_trig_status": self.pr_trig_status,
            "pr_trig_url": self.pr_trig_url,
            "pr_trig_logs": self.pr_trig_logs[-100:],
            "db_status": self.db_status,
            "db_logs": self.db_logs[-100:],
            "setup_status": self.setup_status,
            "setup_logs": self.setup_logs[-100:],
            "build_status": self.build_status,
            "build_logs": self.build_logs[-100:],
        }


_sessions: dict[str, SessionState] = {}


def create_session() -> SessionState:
    session_id = str(uuid.uuid4())
    sess = SessionState(session_id)
    _sessions[session_id] = sess
    return sess


def get_session(session_id: str) -> Optional[SessionState]:
    sess = _sessions.get(session_id)
    if sess:
        sess.last_active = time.time()
    return sess


def get_or_create_session(session_id: str) -> SessionState:
    if session_id not in _sessions:
        _sessions[session_id] = SessionState(session_id)
    _sessions[session_id].last_active = time.time()
    return _sessions[session_id]
