import uuid
from datetime import datetime
from sqlalchemy import Column, String, DateTime, Integer, Float, ForeignKey, Date, UniqueConstraint, Index
from sqlalchemy.orm import relationship
from utils.utils import Base


class Calculationsession(Base):
    __tablename__ = "calculation_sessions"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    session_id = Column(String(255), nullable=False, unique=True, index=True)
    first_access_at = Column(DateTime, nullable=False)
    last_access_at = Column(DateTime, nullable=False)
    calculation_count = Column(Integer, nullable=False, default=0)
    user_agent = Column(String(500), nullable=True)
    ip_address = Column(String(50), nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    calculations = relationship("Calculation", back_populates="session")


class Calculation(Base):
    __tablename__ = "calculations"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    session_id = Column(String(36), ForeignKey("calculation_sessions.id", ondelete="CASCADE"), nullable=False, index=True)
    principal = Column(Float, nullable=False)
    annual_interest_rate = Column(Float, nullable=False)
    loan_term_months = Column(Integer, nullable=False)
    monthly_payment = Column(Float, nullable=False)
    total_interest = Column(Float, nullable=False)
    total_amount = Column(Float, nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    session = relationship("Calculationsession", back_populates="calculations")
    amortization_entries = relationship("Amortizationentry", back_populates="calculation", cascade="all, delete-orphan", passive_deletes=True)


class Amortizationentry(Base):
    __tablename__ = "amortization_entries"

    id = Column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
    calculation_id = Column(String(36), ForeignKey("calculations.id", ondelete="CASCADE"), nullable=False, index=True)
    payment_number = Column(Integer, nullable=False)
    payment_date = Column(Date, nullable=False)
    beginning_balance = Column(Float, nullable=False)
    payment_amount = Column(Float, nullable=False)
    principal_portion = Column(Float, nullable=False)
    interest_portion = Column(Float, nullable=False)
    ending_balance = Column(Float, nullable=False)
    cumulative_interest = Column(Float, nullable=False)
    cumulative_principal = Column(Float, nullable=False)
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)

    calculation = relationship("Calculation", back_populates="amortization_entries")

    __table_args__ = (
        UniqueConstraint("calculation_id", "payment_number", name="uq_calculation_payment_number"),
        Index("ix_amortization_calculation_payment", "calculation_id", "payment_number"),
    )