from sqlalchemy import JSON, UUID, Boolean, Column, DateTime, Float, ForeignKey, Integer, Numeric, String
from sqlalchemy.orm import relationship

from src.database.core import Base
from src.models import DefaultMixin
import uuid

class AerosSimulation(Base, DefaultMixin):
    __tablename__ = "rbd_tr_aeros_simulation"

    status = Column(String, nullable=False)
    started_at = Column(DateTime, nullable=True)
    completed_at = Column(DateTime, nullable=True)
    input = Column(JSON, nullable=True)
    error = Column(JSON, nullable=True)
    simulation_name = Column(String, nullable=False)
    schematic_name = Column(String, nullable=False)
    reliability = Column(JSON, nullable=True)
    duration = Column(Integer, nullable=True)
    offset = Column(Integer, nullable=True)
    is_default = Column(Boolean, default=False)
    created_by = Column(UUID(as_uuid=True), nullable=True)

    calc_results = relationship(
        "AerosSimulationCalcResult", back_populates="aeros_simulation", lazy="raise"
    )

    plot_results = relationship(
        "AerosSimulationPlotResult", back_populates="aeros_simulation", lazy="raise"
    )

class AerosSchematic(Base, DefaultMixin):
    __tablename__ = "rbd_ms_aeros_schematic"

    schematic_name = Column(String, nullable=False)
    alias = Column(String, nullable=False)

class AerosNode(Base, DefaultMixin):
    __tablename__ = "rbd_ms_aeros_node"

    id = Column(
        UUID(as_uuid=True),
        primary_key=True,
        default=uuid.uuid4,
        unique=True,
        nullable=False,
    )
    node_type = Column(String, nullable=False)
    original_node_id = Column(Integer, nullable=False)
    node_id = Column(Integer, nullable=False)
    node_name = Column(String, nullable=False)
    structure_name = Column(String, nullable=False)
    schematic_name = Column(String, nullable=False)
    schematic_id = Column(UUID(as_uuid=True),ForeignKey("rbd_ms_aeros_node.id"), nullable=False)
    original_schematic_id = Column(Integer, nullable=False)
    ref_schematic_id = Column(Integer, nullable=False)
    orignal_ref_schematic_id = Column(Integer, nullable=False)
    aeros_schematic_id = Column(UUID(as_uuid=True),ForeignKey("rbd_ms_aeros_schematic.id") ,nullable=False)
    model_image = Column(JSON, nullable=True)

    parent = relationship(
        "AerosNode",
        remote_side=[id],
        back_populates="children",
        foreign_keys=[schematic_id],
    )

    equipment = relationship(
        "MasterEquipment",
        lazy="selectin",
        primaryjoin="and_(AerosNode.node_name == foreign(MasterEquipment.location_tag))",
        uselist=False,  # Add this if it's a one-to-one relationship
    )

    children = relationship(
        "AerosNode", back_populates="parent", foreign_keys=[schematic_id]
    )

    calc_results = relationship(
        "AerosSimulationCalcResult", back_populates="aeros_node"
    )

    plot_results = relationship(
        "AerosSimulationPlotResult", back_populates="aeros_node"
    )

    aeros_equipment = relationship(
        "AerosEquipment", lazy="selectin", primaryjoin="and_(AerosNode.node_name == foreign(AerosEquipment.node_name))", uselist=False
    )


class AerosSimulationCalcResult(Base, DefaultMixin):
    __tablename__ = "rbd_tr_aeros_simulation_calc_result"

    total_downtime = Column(Float, nullable=False)
    total_uptime = Column(Float, nullable=False)
    num_events = Column(Integer, nullable=False)
    production = Column(Float, nullable=False)
    production_std = Column(Float, nullable=False)
    ideal_production = Column(Float, nullable=False)
    availability = Column(Float, nullable=False)
    efficiency = Column(Float, nullable=False)
    effective_loss = Column(Float, nullable=False)
    num_cm = Column(Integer, nullable=False)
    cm_waiting_time = Column(Float, nullable=False)
    total_cm_downtime = Column(Float, nullable=False)
    num_pm = Column(Integer, nullable=False)
    total_pm_downtime = Column(Float, nullable=False)
    num_ip = Column(Integer, nullable=False)
    total_ip_downtime = Column(Float, nullable=False)
    num_oh = Column(Integer, nullable=False)
    total_oh_downtime = Column(Float, nullable=False)
    t_wait_for_crew = Column(Float, nullable=False)
    t_wait_for_spare = Column(Float, nullable=False)
    duration_at_full = Column(Float, nullable=False)
    duration_above_hh = Column(Float, nullable=False)
    duration_above_h = Column(Float, nullable=False)
    duration_below_l = Column(Float, nullable=False)
    duration_below_ll = Column(Float, nullable=False)
    duration_at_empty = Column(Float, nullable=False)
    stg_input = Column(Float, nullable=True)
    stg_output = Column(Float, nullable=True)
    average_level = Column(Float, nullable=True)
    potential_production = Column(Float, nullable=True)
    eaf = Column(Float, nullable=True)
    eaf_konkin = Column(Float, nullable=True, default=0)
    efor = Column(Float, nullable=True)
    derating_hours = Column(Float, nullable=True)
    eta = Column(Float, nullable=True)
    beta = Column(Float, nullable=True)
    mttr = Column(Integer, nullable=True)
    parameters = Column(JSON, nullable=True)
    contribution = Column(Float, nullable=True)
    criticality = Column(Float, nullable=True)
    contribution_factor = Column(Float, nullable=True)
    total_mo_downtime = Column(Float, nullable=True)
    total_po_downtime = Column(Float, nullable=True)
    sof = Column(Float, nullable=True)

    aeros_simulation_id = Column(
        UUID(as_uuid=True), ForeignKey("rbd_tr_aeros_simulation.id"), nullable=False
    )
    aeros_node_id = Column(
        UUID(as_uuid=True), ForeignKey("rbd_ms_aeros_node.id"), nullable=False
    )

    aeros_node = relationship("AerosNode", back_populates="calc_results", lazy="raise")

    aeros_simulation = relationship(
        "AerosSimulation", back_populates="calc_results", lazy="raise"
    )


class AerosSimulationPlotResult(Base, DefaultMixin):
    __tablename__ = "rbd_tr_aeros_simulation_plot_result"

    max_flow_rate = Column(Numeric, nullable=False)
    storage_capacity = Column(Numeric, nullable=False)
    point_availabilities = Column(JSON, nullable=False)
    point_flowrates = Column(JSON, nullable=False)
    timestamp_outs = Column(JSON, nullable=False)

    aeros_simulation_id = Column(
        UUID(as_uuid=True), ForeignKey("rbd_tr_aeros_simulation.id"), nullable=False
    )
    aeros_node_id = Column(
        UUID(as_uuid=True), ForeignKey("rbd_ms_aeros_node.id"), nullable=False
    )

    aeros_node = relationship("AerosNode", back_populates="plot_results", lazy="raise")

    aeros_simulation = relationship(
        "AerosSimulation", back_populates="plot_results", lazy="raise"
    )


class EafContribution(Base, DefaultMixin):
    __tablename__ = "rbd_ms_eaf_contribution"

    location_tag = Column(String, nullable=False)
    eaf_contribution = Column(Float, nullable=False)
    efficiency_uptime = Column(Float, nullable=False)
    edh = Column(Float, nullable=False)
    
    
    
# models.py
class AerosSimulationProgress(Base):
    __tablename__ = "simulation_progress"
    simulation_id = Column(Integer, primary_key=True)
    status = Column(String, default="pending")  # pending, running, failed, completed
    step = Column(String, nullable=True)
    progress = Column(Integer, default=0)  # 0-100
    error_message = Column(String, nullable=True)
