"""Simulation result model."""
import json
from datetime import datetime
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, Float

from ..database import Base


class SimulationResult(Base):
    """A single simulation result row (from scan_results.csv).

    P3-M1: Extended with fidelity level, confidence grade,
    constraint margins, surrogate prediction, and cross-validation
    per third-party review.
    """
    __tablename__ = "simulation_results"

    id = Column(Integer, primary_key=True, index=True)
    plan_id = Column(Integer, ForeignKey("simulation_plans.id"), nullable=False, index=True)
    run_index = Column(Integer, default=0)
    status = Column(String(20), default="OK")  # OK / FAILED / UNCERTAIN
    solve_time_s = Column(Float, default=0.0)
    params_json = Column(Text, default="{}")  # JSON: parameter values
    metrics_json = Column(Text, default="{}")  # JSON: metric values
    error_message = Column(Text, default="")
    created_at = Column(DateTime, default=datetime.utcnow)

    # P3: Multi-fidelity and confidence fields
    fidelity_level = Column(String(30), default="L1_motorcad_emag", index=True)  # L0-L4
    confidence_grade = Column(String(2), default="C", index=True)  # A/B/C/D
    model_template_version = Column(String(100), default="")  # Motor-CAD template / PCB model version
    solver_settings_hash = Column(String(64), default="")  # Hash of solver config
    constraint_margins_json = Column(Text, default="{}")  # JSON: hard constraint margins
    surrogate_prediction_json = Column(Text, default="{}")  # JSON: surrogate prediction + uncertainty
    cross_validation_json = Column(Text, default="{}")  # JSON: Motor-CAD vs Maxwell/JMAG deviation
    convergence_status_json = Column(Text, default="{}")  # JSON: six-type convergence status

    def get_params(self) -> dict:
        try:
            return json.loads(self.params_json) if self.params_json else {}
        except (json.JSONDecodeError, TypeError):
            return {}

    def set_params(self, data: dict) -> None:
        self.params_json = json.dumps(data, ensure_ascii=False)

    def get_metrics(self) -> dict:
        try:
            return json.loads(self.metrics_json) if self.metrics_json else {}
        except (json.JSONDecodeError, TypeError):
            return {}

    def set_metrics(self, data: dict) -> None:
        self.metrics_json = json.dumps(data, ensure_ascii=False)

    # P3: Helper methods for extended fields
    def get_constraint_margins(self) -> dict:
        try:
            return json.loads(self.constraint_margins_json) if self.constraint_margins_json else {}
        except (json.JSONDecodeError, TypeError):
            return {}

    def set_constraint_margins(self, data: dict) -> None:
        self.constraint_margins_json = json.dumps(data, ensure_ascii=False)

    def get_surrogate_prediction(self) -> dict:
        try:
            return json.loads(self.surrogate_prediction_json) if self.surrogate_prediction_json else {}
        except (json.JSONDecodeError, TypeError):
            return {}

    def set_surrogate_prediction(self, data: dict) -> None:
        self.surrogate_prediction_json = json.dumps(data, ensure_ascii=False)

    def get_cross_validation(self) -> dict:
        try:
            return json.loads(self.cross_validation_json) if self.cross_validation_json else {}
        except (json.JSONDecodeError, TypeError):
            return {}

    def set_cross_validation(self, data: dict) -> None:
        self.cross_validation_json = json.dumps(data, ensure_ascii=False)

    def get_convergence_status(self) -> dict:
        try:
            return json.loads(self.convergence_status_json) if self.convergence_status_json else {}
        except (json.JSONDecodeError, TypeError):
            return {}

    def set_convergence_status(self, data: dict) -> None:
        self.convergence_status_json = json.dumps(data, ensure_ascii=False)
