import uuid
from datetime import datetime, timezone
from typing import List, Optional
from sqlalchemy import Boolean, Date, DateTime, Float, ForeignKey, Integer, String
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.database import Base


class Investment(Base):
    __tablename__ = "investments"

    id: Mapped[str] = mapped_column(
        String, primary_key=True, default=lambda: str(uuid.uuid4())
    )

    # Institution
    bank: Mapped[str] = mapped_column(String, nullable=False)
    platform: Mapped[Optional[str]] = mapped_column(String, nullable=True)

    # Identity
    investment_number: Mapped[str] = mapped_column(String, nullable=False)
    investment_type: Mapped[str] = mapped_column(String, nullable=False)
    investment_name: Mapped[str] = mapped_column(String, nullable=False)

    # Currency
    currency: Mapped[str] = mapped_column(String, nullable=False, default="IDR")
    kurs_beli: Mapped[float] = mapped_column(Float, nullable=False, default=1.0)

    # Ownership
    owner_name: Mapped[str] = mapped_column(String, nullable=False)

    # Dates
    investment_date: Mapped[datetime] = mapped_column(Date, nullable=False)
    tenor_months: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    maturity_date: Mapped[Optional[datetime]] = mapped_column(Date, nullable=True)

    # Units & face value (for bonds)
    units: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
    face_value_per_unit: Mapped[int] = mapped_column(
        Integer, nullable=False, default=1_000_000
    )
    purchase_price: Mapped[float] = mapped_column(
        Float, nullable=False, default=100.0
    )  # % of face value

    # nominal_idr = stored for convenience (units × face_value_per_unit × kurs_beli)
    nominal_idr: Mapped[int] = mapped_column(Integer, nullable=False, default=0)

    # Interest / Coupon
    interest_rate: Mapped[float] = mapped_column(Float, nullable=False, default=0.0)
    coupon_frequency: Mapped[str] = mapped_column(
        String, nullable=False, default="at_maturity"
    )
    next_coupon_date: Mapped[Optional[datetime]] = mapped_column(Date, nullable=True)

    # Tax
    tax_rate: Mapped[float] = mapped_column(Float, nullable=False, default=0.0)
    is_tax_inclusive: Mapped[bool] = mapped_column(
        Boolean, nullable=False, default=False
    )

    # Status
    status: Mapped[str] = mapped_column(String, nullable=False, default="active")
    sold_date: Mapped[Optional[datetime]] = mapped_column(Date, nullable=True)
    sold_price: Mapped[Optional[float]] = mapped_column(Float, nullable=True)

    # Notes
    notes: Mapped[Optional[str]] = mapped_column(String, nullable=True)

    # Timestamps
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True),
        default=lambda: datetime.now(timezone.utc),
        onupdate=lambda: datetime.now(timezone.utc),
    )

    # Relationships
    attachments: Mapped[List["InvestmentAttachment"]] = relationship(
        "InvestmentAttachment",
        back_populates="investment",
        cascade="all, delete-orphan",
        order_by="InvestmentAttachment.created_at",
    )


class InvestmentAttachment(Base):
    __tablename__ = "investment_attachments"

    id: Mapped[str] = mapped_column(
        String, primary_key=True, default=lambda: str(uuid.uuid4())
    )
    investment_id: Mapped[str] = mapped_column(
        String, ForeignKey("investments.id", ondelete="CASCADE"), nullable=False
    )
    google_drive_file_id: Mapped[str] = mapped_column(String, nullable=False)
    google_drive_view_url: Mapped[str] = mapped_column(String, nullable=False)
    original_filename: Mapped[str] = mapped_column(String, nullable=False)
    content_type: Mapped[str] = mapped_column(String, nullable=False)
    file_size: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
    )

    # Relationship
    investment: Mapped["Investment"] = relationship(
        "Investment", back_populates="attachments"
    )
