from datetime import datetime, date, timezone
from decimal import Decimal
from sqlalchemy import (
    String, Boolean, Date, DateTime, DECIMAL, Integer, SmallInteger,
    ForeignKey, Text, JSON
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.database import Base


class VehicleRegistry(Base):
    __tablename__ = "vehicle_registry"

    plate: Mapped[str] = mapped_column(String(10), primary_key=True)
    vin: Mapped[str | None] = mapped_column(String(17))
    vehicle_type: Mapped[str | None] = mapped_column(String(50))
    registration_date: Mapped[date | None] = mapped_column(Date)
    homologation_code: Mapped[str | None] = mapped_column(String(50))
    engine_code: Mapped[str | None] = mapped_column(String(20))
    last_revision_date: Mapped[date | None] = mapped_column(Date)
    foreign_plate: Mapped[str | None] = mapped_column(String(20))
    foreign_registration_date: Mapped[date | None] = mapped_column(Date)
    foreign_country: Mapped[str | None] = mapped_column(String(50))
    is_foreign_registered: Mapped[bool | None] = mapped_column(Boolean)
    source: Mapped[str | None] = mapped_column(String(20))
    raw_response: Mapped[dict | None] = mapped_column(JSON)
    fetched_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    selected_motornet_code: Mapped[str | None] = mapped_column(String(20))

    version_candidates: Mapped[list["PlateVersionCandidate"]] = relationship(
        "PlateVersionCandidate", back_populates="registry"
    )


class VehicleVersion(Base):
    __tablename__ = "vehicle_versions"

    motornet_code: Mapped[str] = mapped_column(String(20), primary_key=True)
    brand_acronym: Mapped[str | None] = mapped_column(String(10))
    brand_name: Mapped[str | None] = mapped_column(String(50))
    model_code: Mapped[str | None] = mapped_column(String(10))
    model_description: Mapped[str | None] = mapped_column(String(100))
    gamma_code: Mapped[str | None] = mapped_column(String(10))
    gamma_description: Mapped[str | None] = mapped_column(String(100))
    series_code: Mapped[str | None] = mapped_column(String(10))
    series_description: Mapped[str | None] = mapped_column(String(100))
    historical_group_code: Mapped[str | None] = mapped_column(String(10))
    historical_group_desc: Mapped[str | None] = mapped_column(String(100))
    cod_desc_model_code: Mapped[str | None] = mapped_column(String(10))
    cod_desc_model_desc: Mapped[str | None] = mapped_column(String(100))
    version_label: Mapped[str | None] = mapped_column(String(200))
    body_type: Mapped[str | None] = mapped_column(String(10))
    doors: Mapped[int | None] = mapped_column(SmallInteger)
    wheelbase: Mapped[int | None] = mapped_column(SmallInteger)
    list_price: Mapped[Decimal | None] = mapped_column(DECIMAL(10, 2))
    production_start: Mapped[date | None] = mapped_column(Date)
    production_end: Mapped[date | None] = mapped_column(Date)
    commercial_start: Mapped[date | None] = mapped_column(Date)
    commercial_end: Mapped[date | None] = mapped_column(Date)
    first_seen_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    last_seen_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    seen_count: Mapped[int] = mapped_column(Integer, default=1)
    source: Mapped[str | None] = mapped_column(String(20))

    plate_candidates: Mapped[list["PlateVersionCandidate"]] = relationship(
        "PlateVersionCandidate", back_populates="version"
    )


class PlateVersionCandidate(Base):
    __tablename__ = "plate_version_candidates"

    plate: Mapped[str] = mapped_column(
        String(10), ForeignKey("vehicle_registry.plate"), primary_key=True
    )
    motornet_code: Mapped[str] = mapped_column(
        String(20), ForeignKey("vehicle_versions.motornet_code"), primary_key=True
    )
    is_selected: Mapped[bool] = mapped_column(Boolean, default=False)

    registry: Mapped["VehicleRegistry"] = relationship(
        "VehicleRegistry", back_populates="version_candidates"
    )
    version: Mapped["VehicleVersion"] = relationship(
        "VehicleVersion", back_populates="plate_candidates"
    )


class ApiUsageLog(Base):
    __tablename__ = "api_usage_log"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
    source: Mapped[str | None] = mapped_column(String(20))
    plate: Mapped[str | None] = mapped_column(String(10))
    hit_cache: Mapped[bool] = mapped_column(Boolean, default=False)
    remaining_queries: Mapped[int | None] = mapped_column(Integer)
    called_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
    )
