"""Phase 5.10 — Financial Reporting & BI domain models."""
from __future__ import annotations

import uuid
from datetime import date, datetime
from decimal import Decimal

from sqlalchemy import Boolean, Date, DateTime, Index, Integer, Numeric, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column

from app.core.database import Base
from app.models.base import TenantMixin, TimestampMixin, UUIDPrimaryKeyMixin
from app.models.types import GUID, ReportExportFormat, ReportStatus, ReportType


class FinancialReport(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "financial_reports"

    report_type: Mapped[ReportType] = mapped_column(nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    fiscal_period_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    fiscal_year_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    generated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    status: Mapped[ReportStatus] = mapped_column(default=ReportStatus.GENERATED, nullable=False)
    report_data: Mapped[str | None] = mapped_column(Text, nullable=True)
    generated_by: Mapped[str | None] = mapped_column(String(100), nullable=True)

    __table_args__ = (
        Index("ix_financial_reports_tenant_type", "tenant_id", "report_type"),
    )


class ReportTemplate(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "report_templates"

    name: Mapped[str] = mapped_column(String(255), nullable=False)
    report_type: Mapped[ReportType] = mapped_column(nullable=False)
    template_config: Mapped[str] = mapped_column(Text, nullable=False)
    is_system: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)

    __table_args__ = (UniqueConstraint("tenant_id", "name", name="uq_report_template_tenant_name"),)


class Dashboard(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "dashboards"

    name: Mapped[str] = mapped_column(String(255), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    dashboard_type: Mapped[str] = mapped_column(String(50), nullable=False)
    layout_config: Mapped[str | None] = mapped_column(Text, nullable=True)
    is_default: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)

    __table_args__ = (UniqueConstraint("tenant_id", "name", name="uq_dashboard_tenant_name"),)


class DashboardWidget(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "dashboard_widgets"

    dashboard_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    widget_type: Mapped[str] = mapped_column(String(50), nullable=False)
    title: Mapped[str] = mapped_column(String(255), nullable=False)
    config: Mapped[str | None] = mapped_column(Text, nullable=True)
    position: Mapped[int] = mapped_column(Integer, default=0, nullable=False)


class KPI(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "kpis"

    code: Mapped[str] = mapped_column(String(50), nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    kpi_type: Mapped[str] = mapped_column(String(50), nullable=False)
    current_value: Mapped[Decimal | None] = mapped_column(Numeric(18, 4), nullable=True)
    target_value: Mapped[Decimal | None] = mapped_column(Numeric(18, 4), nullable=True)
    calculated_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)

    __table_args__ = (UniqueConstraint("tenant_id", "code", name="uq_kpi_tenant_code"),)


class ReportSnapshot(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "report_snapshots"

    report_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    snapshot_date: Mapped[date] = mapped_column(Date, nullable=False)
    snapshot_data: Mapped[str] = mapped_column(Text, nullable=False)


class ScheduledReport(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "scheduled_reports"

    template_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    report_type: Mapped[ReportType] = mapped_column(nullable=False)
    schedule_cron: Mapped[str] = mapped_column(String(100), nullable=False)
    recipients: Mapped[str | None] = mapped_column(Text, nullable=True)
    is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
    last_run_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)


class ReportExport(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "report_exports"

    report_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    export_format: Mapped[ReportExportFormat] = mapped_column(nullable=False)
    file_path: Mapped[str | None] = mapped_column(String(500), nullable=True)
    exported_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    exported_by: Mapped[str | None] = mapped_column(String(100), nullable=True)


class ReportHistory(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "report_history"

    report_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    action: Mapped[str] = mapped_column(String(50), nullable=False)
    actor_user_id: Mapped[str] = mapped_column(String(100), nullable=False)


class ReportConfiguration(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin):
    __tablename__ = "report_configurations"

    key: Mapped[str] = mapped_column(String(100), nullable=False)
    value: Mapped[str | None] = mapped_column(Text, nullable=True)

    __table_args__ = (UniqueConstraint("tenant_id", "key", name="uq_report_config_tenant_key"),)
