
"""Boris state management - data models and persistence."""
import json
import os
from dataclasses import dataclass, field, asdict
from datetime import datetime
from typing import Optional

import config


@dataclass
class Milestone:
    id: str
    title: str
    description: str
    depends_on: list[str]
    acceptance_criteria: list[str]
    files_to_create: list[str]
    files_to_modify: list[str]
    status: str = "pending"  # pending | in_progress | completed | skipped
    retry_count: int = 0
    completed_at: Optional[str] = None


@dataclass
class UIMilestone:
    id: str
    title: str
    description: str
    test_tool: str
    test_commands: list[str]
    acceptance_criteria: list[str]
    issues_found: list[str] = field(default_factory=list)
    issues_fixed: list[str] = field(default_factory=list)
    status: str = "pending"
    retry_count: int = 0
    completed_at: Optional[str] = None


@dataclass
class UIPlan:
    project_type: str
    test_tool: str
    milestones: list[UIMilestone]


@dataclass
class Plan:
    task: str
    milestones: list[Milestone]
    created_at: str = field(default_factory=lambda: datetime.now().isoformat())


@dataclass
class State:
    plan: Plan
    current_milestone_index: int
    project_dir: str
    git_remote: Optional[str]
    no_git: bool
    started_at: str = field(default_factory=lambda: datetime.now().isoformat())
    updated_at: str = field(default_factory=lambda: datetime.now().isoformat())
    phase: str = "structural"  # structural | ui_testing
    ui_plan: Optional[UIPlan] = None


def save(state: State) -> None:
    """Save state to {project_dir}/.boris/state.json."""
    state_dir = os.path.join(state.project_dir, config.STATE_DIR)
    os.makedirs(state_dir, exist_ok=True)
    state_path = os.path.join(state_dir, config.STATE_FILE)
    state.updated_at = datetime.now().isoformat()
    with open(state_path, "w", encoding="utf-8") as f:
        json.dump(asdict(state), f, indent=2, ensure_ascii=False)


def load(project_dir: str) -> Optional[State]:
    """Load state from {project_dir}/.boris/state.json. Returns None if not found."""
    state_path = os.path.join(project_dir, config.STATE_DIR, config.STATE_FILE)
    if not os.path.exists(state_path):
        return None
    try:
        with open(state_path, "r", encoding="utf-8") as f:
            data = json.load(f)
        # Reconstruct dataclass instances from dicts
        milestones = [Milestone(**m) for m in data["plan"]["milestones"]]
        plan = Plan(
            task=data["plan"]["task"],
            milestones=milestones,
            created_at=data["plan"]["created_at"],
        )
        return State(
            plan=plan,
            current_milestone_index=data["current_milestone_index"],
            project_dir=data["project_dir"],
            git_remote=data.get("git_remote"),
            no_git=data.get("no_git", False),
            started_at=data.get("started_at", ""),
            updated_at=data.get("updated_at", ""),
        )
    except (json.JSONDecodeError, KeyError, TypeError):
        return None
