from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional


@dataclass
class PeptideJobSubmission:
    success: bool
    message: str
    job_id: Optional[str] = None
    peptide_job_id: Optional[str] = None

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


@dataclass
class PeptideJob:
    job_id: str
    job_name: str
    status: str
    protein_file_name: Optional[str] = None
    total_requested: int = 0
    generated: int = 0
    completed: int = 0
    failed: int = 0
    pending: int = 0
    created_at: Optional[str] = None
    completed_at: Optional[str] = None
    pocket_coord: Optional[list[float]] = None
    noise_mode: Optional[str] = None
    input_peptide_name: Optional[str] = None
    design_mode: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> PeptideJob:
        return cls(
            job_id=data.get("job_id", ""),
            job_name=data.get("job_name", ""),
            status=data.get("status", ""),
            protein_file_name=data.get("protein_file_name"),
            total_requested=data.get("total_requested", 0),
            generated=data.get("generated", 0),
            completed=data.get("completed", 0),
            failed=data.get("failed", 0),
            pending=data.get("pending", 0),
            created_at=data.get("created_at"),
            completed_at=data.get("completed_at"),
            pocket_coord=data.get("pocket_coord"),
            noise_mode=data.get("noise_mode"),
            input_peptide_name=data.get("input_peptide_name"),
            design_mode=data.get("design_mode"),
        )


@dataclass
class PeptideJobStatus:
    success: bool
    message: Optional[str] = None
    job_id: Optional[str] = None
    peptide_job_id: Optional[str] = None
    job_name: Optional[str] = None
    protein_file_name: Optional[str] = None
    job_status: Optional[str] = None
    design_mode: Optional[str] = None
    input_peptide_name: Optional[str] = None
    total_requested: int = 0
    total_generated: int = 0
    completed: int = 0
    failed: int = 0
    pending: int = 0
    pocket_coord: Optional[list[float]] = None
    radius: Optional[int] = None

    @classmethod
    def from_dict(cls, data: dict) -> PeptideJobStatus:
        return cls(
            success=data.get("success", False),
            message=data.get("message"),
            job_id=data.get("job_id"),
            peptide_job_id=data.get("peptide_job_id"),
            job_name=data.get("job_name"),
            protein_file_name=data.get("protein_file_name"),
            job_status=data.get("job_status"),
            design_mode=data.get("design_mode"),
            input_peptide_name=data.get("input_peptide_name"),
            total_requested=data.get("total_requested", 0),
            total_generated=data.get("total_generated", 0),
            completed=data.get("completed", 0),
            failed=data.get("failed", 0),
            pending=data.get("pending", 0),
            pocket_coord=data.get("pocket_coord"),
            radius=data.get("radius"),
        )


@dataclass
class PeptideInfo:
    id: str
    aa_sequence: Optional[str] = None
    smiles: Optional[str] = None
    confidence_score: Optional[float] = None
    confidence_pos: Optional[float] = None
    confidence_node: Optional[float] = None
    tag: Optional[str] = None
    pdb_path: Optional[str] = None
    sdf_path: Optional[str] = None
    json_path: Optional[str] = None
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> PeptideInfo:
        return cls(
            id=data.get("id", ""),
            aa_sequence=data.get("aa_sequence"),
            smiles=data.get("smiles"),
            confidence_score=data.get("confidence_score"),
            confidence_pos=data.get("confidence_pos"),
            confidence_node=data.get("confidence_node"),
            tag=data.get("tag"),
            pdb_path=data.get("pdb_path"),
            sdf_path=data.get("sdf_path"),
            json_path=data.get("json_path"),
            created_at=data.get("created_at"),
        )


@dataclass
class PeptideResults:
    success: bool
    message: Optional[str] = None
    job_name: Optional[str] = None
    protein_file_name: Optional[str] = None
    total: int = 0
    limit: int = 50
    offset: int = 0
    peptides: list[PeptideInfo] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> PeptideResults:
        return cls(
            success=data.get("success", False),
            message=data.get("message"),
            job_name=data.get("job_name"),
            protein_file_name=data.get("protein_file_name"),
            total=data.get("total", 0),
            limit=data.get("limit", 50),
            offset=data.get("offset", 0),
            peptides=[PeptideInfo.from_dict(p) for p in data.get("peptides", [])],
        )


@dataclass
class PeptideDetail:
    success: bool
    message: Optional[str] = None
    id: Optional[str] = None
    aa_sequence: Optional[str] = None
    smiles: Optional[str] = None
    confidence_score: Optional[float] = None
    confidence_pos: Optional[float] = None
    confidence_node: Optional[float] = None
    tag: Optional[str] = None
    pdb_content: Optional[str] = None
    sdf_content: Optional[str] = None
    json_data: Optional[dict] = None
    pdb_path: Optional[str] = None
    sdf_path: Optional[str] = None
    json_path: Optional[str] = None
    created_at: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> PeptideDetail:
        return cls(
            success=data.get("success", False),
            message=data.get("message"),
            id=data.get("id"),
            aa_sequence=data.get("aa_sequence"),
            smiles=data.get("smiles"),
            confidence_score=data.get("confidence_score"),
            confidence_pos=data.get("confidence_pos"),
            confidence_node=data.get("confidence_node"),
            tag=data.get("tag"),
            pdb_content=data.get("pdb_content"),
            sdf_content=data.get("sdf_content"),
            json_data=data.get("json_data"),
            pdb_path=data.get("pdb_path"),
            sdf_path=data.get("sdf_path"),
            json_path=data.get("json_path"),
            created_at=data.get("created_at"),
        )


@dataclass
class PeptideConfidenceStats:
    best: Optional[float] = None
    worst: Optional[float] = None
    avg: Optional[float] = None
    count: Optional[int] = None

    @classmethod
    def from_dict(cls, data: dict) -> PeptideConfidenceStats:
        return cls(
            best=data.get("best"),
            worst=data.get("worst"),
            avg=data.get("avg"),
            count=data.get("count"),
        )


@dataclass
class PeptideSummaryStats:
    total_peptides: int = 0
    confidence_stats: Optional[PeptideConfidenceStats] = None

    @classmethod
    def from_dict(cls, data: dict) -> PeptideSummaryStats:
        cs_raw = data.get("confidence_stats")
        return cls(
            total_peptides=data.get("total_peptides", 0),
            confidence_stats=PeptideConfidenceStats.from_dict(cs_raw) if cs_raw else None,
        )


@dataclass
class TopPeptide:
    id: str
    aa_sequence: Optional[str] = None
    smiles: Optional[str] = None
    confidence_score: Optional[float] = None
    tag: Optional[str] = None

    @classmethod
    def from_dict(cls, data: dict) -> TopPeptide:
        return cls(
            id=data.get("id", ""),
            aa_sequence=data.get("aa_sequence"),
            smiles=data.get("smiles"),
            confidence_score=data.get("confidence_score"),
            tag=data.get("tag"),
        )


@dataclass
class PeptideSummary:
    success: bool
    message: Optional[str] = None
    job_name: Optional[str] = None
    protein_file_name: Optional[str] = None
    summary: Optional[PeptideSummaryStats] = None
    top_peptides: list[TopPeptide] = field(default_factory=list)

    @classmethod
    def from_dict(cls, data: dict) -> PeptideSummary:
        summary_raw = data.get("summary")
        return cls(
            success=data.get("success", False),
            message=data.get("message"),
            job_name=data.get("job_name"),
            protein_file_name=data.get("protein_file_name"),
            summary=PeptideSummaryStats.from_dict(summary_raw) if summary_raw else None,
            top_peptides=[TopPeptide.from_dict(p) for p in data.get("top_peptides", [])],
        )


@dataclass
class PeptideDownsyncResult:
    success: bool
    message: Optional[str] = None
    synced: int = 0
    skipped: int = 0
    failed: int = 0
    total: int = 0

    @classmethod
    def from_dict(cls, data: dict) -> PeptideDownsyncResult:
        return cls(
            success=data.get("success", False),
            message=data.get("message"),
            synced=data.get("synced", 0),
            skipped=data.get("skipped", 0),
            failed=data.get("failed", 0),
            total=data.get("total", 0),
        )
