from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Optional


@dataclass
class ExperimentResponse:
    success: bool
    experiment_id: Optional[str] = None
    experiment_name: Optional[str] = None
    message: Optional[str] = None
    created: Optional[bool] = None

    @classmethod
    def from_dict(cls, data: dict) -> ExperimentResponse:
        return cls(
            success=data.get("success", False),
            experiment_id=data.get("experiment_id"),
            experiment_name=data.get("experiment_name"),
            message=data.get("message"),
            created=data.get("created"),
        )


@dataclass
class ExperimentSummary:
    experiment_id: str
    job_name: str
    experiment_name: str
    description: Optional[str] = None
    simulation_count: int = 0
    latest_status: Optional[str] = None
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> ExperimentSummary:
        return cls(
            experiment_id=data.get("experiment_id", ""),
            job_name=data.get("job_name", ""),
            experiment_name=data.get("experiment_name", ""),
            description=data.get("description"),
            simulation_count=data.get("simulation_count", 0),
            latest_status=data.get("latest_status"),
            created_at=data.get("created_at"),
        )


@dataclass
class SimulationSummary:
    md_id: int
    job_id: str
    run_number: int
    status: str
    sim_type: Optional[str] = None
    protein_file: Optional[str] = None
    ligand_file: Optional[str] = None
    cofactor_file: Optional[str] = None
    forcefield: Optional[str] = None
    water_model: Optional[str] = None
    has_membrane: bool = False
    simulation_ns: Optional[float] = None
    progress_percent: float = 0.0
    current_step: int = 0
    total_steps: int = 0
    error_message: Optional[str] = None
    started_at: Optional[str] = None
    completed_at: Optional[str] = None
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> SimulationSummary:
        return cls(
            md_id=data.get("md_id", 0),
            job_id=data.get("job_id", ""),
            run_number=data.get("run_number", 0),
            status=data.get("status", ""),
            sim_type=data.get("sim_type"),
            protein_file=data.get("protein_file"),
            ligand_file=data.get("ligand_file"),
            cofactor_file=data.get("cofactor_file"),
            forcefield=data.get("forcefield"),
            water_model=data.get("water_model"),
            has_membrane=data.get("has_membrane", False),
            simulation_ns=data.get("simulation_ns"),
            progress_percent=data.get("progress_percent", 0.0),
            current_step=data.get("current_step", 0),
            total_steps=data.get("total_steps", 0),
            error_message=data.get("error_message"),
            started_at=data.get("started_at"),
            completed_at=data.get("completed_at"),
            created_at=data.get("created_at"),
        )


@dataclass
class ExperimentDetail:
    success: bool
    experiment_id: Optional[str] = None
    job_name: Optional[str] = None
    experiment_name: Optional[str] = None
    description: Optional[str] = None
    simulations: list[SimulationSummary] = field(default_factory=list)
    created_at: Optional[str] = None
    message: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> ExperimentDetail:
        return cls(
            success=data.get("success", False),
            experiment_id=data.get("experiment_id"),
            job_name=data.get("job_name"),
            experiment_name=data.get("experiment_name"),
            description=data.get("description"),
            simulations=[
                SimulationSummary.from_dict(s) for s in data.get("simulations") or []
            ],
            created_at=data.get("created_at"),
            message=data.get("message"),
        )


@dataclass
class StartSimulationResponse:
    success: bool
    message: Optional[str] = None
    job_id: Optional[str] = None
    experiment_id: Optional[str] = None
    experiment_name: Optional[str] = None
    run_number: Optional[int] = None
    is_resumption: bool = False

    @classmethod
    def from_dict(cls, data: dict) -> StartSimulationResponse:
        return cls(
            success=data.get("success", False),
            message=data.get("message"),
            job_id=data.get("job_id"),
            experiment_id=data.get("experiment_id"),
            experiment_name=data.get("experiment_name"),
            run_number=data.get("run_number"),
            is_resumption=data.get("is_resumption", False),
        )


@dataclass
class SimulationStatus:
    success: bool
    experiment_id: Optional[str] = None
    experiment_name: Optional[str] = None
    job_name: Optional[str] = None
    md_id: Optional[int] = None
    job_id: Optional[str] = None
    run_number: Optional[int] = None
    status: Optional[str] = None
    sim_type: Optional[str] = None
    progress_percent: float = 0.0
    current_step: int = 0
    total_steps: int = 0
    started_at: Optional[str] = None
    completed_at: Optional[str] = None
    error_message: Optional[str] = None
    simulation_ns: Optional[float] = None
    forcefield: Optional[str] = None
    water_model: Optional[str] = None
    message: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> SimulationStatus:
        return cls(
            success=data.get("success", False),
            experiment_id=data.get("experiment_id"),
            experiment_name=data.get("experiment_name"),
            job_name=data.get("job_name"),
            md_id=data.get("md_id"),
            job_id=data.get("job_id"),
            run_number=data.get("run_number"),
            status=data.get("status"),
            sim_type=data.get("sim_type"),
            progress_percent=data.get("progress_percent", 0.0),
            current_step=data.get("current_step", 0),
            total_steps=data.get("total_steps", 0),
            started_at=data.get("started_at"),
            completed_at=data.get("completed_at"),
            error_message=data.get("error_message"),
            simulation_ns=data.get("simulation_ns"),
            forcefield=data.get("forcefield"),
            water_model=data.get("water_model"),
            message=data.get("message"),
        )


@dataclass
class ActionResponse:
    success: bool
    message: Optional[str] = None
    job_id: Optional[str] = None
    experiment_id: Optional[str] = None
    run_number: Optional[int] = None
    is_resumption: bool = False

    @classmethod
    def from_dict(cls, data: dict) -> ActionResponse:
        return cls(
            success=data.get("success", False),
            message=data.get("message"),
            job_id=data.get("job_id"),
            experiment_id=data.get("experiment_id"),
            run_number=data.get("run_number"),
            is_resumption=data.get("is_resumption", False),
        )


@dataclass
class AnalysisReport:
    rmsd: Optional[dict[str, Any]] = None
    rmsf: Optional[dict[str, Any]] = None
    radius_of_gyration: Optional[dict[str, Any]] = None
    energies: Optional[dict[str, Any]] = None
    ligand_interactions: Optional[dict[str, Any]] = None
    ligand_distance: Optional[dict[str, Any]] = None

    @classmethod
    def from_dict(cls, data: dict) -> AnalysisReport:
        return cls(
            rmsd=data.get("rmsd"),
            rmsf=data.get("rmsf"),
            radius_of_gyration=data.get("radius_of_gyration"),
            energies=data.get("energies"),
            ligand_interactions=data.get("ligand_interactions"),
            ligand_distance=data.get("ligand_distance"),
        )


@dataclass
class SimulationResults:
    success: bool
    status: Optional[str] = None
    job_id: Optional[str] = None
    job_name: Optional[str] = None
    analysis_report: Optional[AnalysisReport] = None
    video_url: Optional[str] = None
    file_urls: Optional[dict[str, str]] = None
    message: Optional[str] = None
    raw: Optional[dict[str, Any]] = None

    @classmethod
    def from_dict(cls, data: dict) -> SimulationResults:
        report_raw = data.get("analysis_report")
        return cls(
            success=data.get("success", False),
            status=data.get("status"),
            job_id=data.get("job_id"),
            job_name=data.get("job_name"),
            analysis_report=AnalysisReport.from_dict(report_raw) if report_raw else None,
            video_url=data.get("video_url"),
            file_urls=data.get("file_urls"),
            message=data.get("message"),
            raw=data,
        )


@dataclass
class TopologyResponse:
    success: bool
    content: Optional[str] = None
    message: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> TopologyResponse:
        return cls(
            success=data.get("success", False),
            content=data.get("content"),
            message=data.get("message"),
        )


@dataclass
class ResourceResponse:
    success: bool
    content: Optional[str] = None
    filename: Optional[str] = None
    message: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> ResourceResponse:
        return cls(
            success=data.get("success", False),
            content=data.get("content"),
            filename=data.get("filename"),
            message=data.get("message"),
        )
