from __future__ import annotations

from datetime import date, datetime, timezone

from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column

from app.core.db.common import CommonBase


def utcnow() -> datetime:
    return datetime.now(timezone.utc)


class CredentialVaultEntry(CommonBase):
    __tablename__ = "credential_vault_entries"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), index=True)
    client_id: Mapped[int | None] = mapped_column(ForeignKey("clients.id", ondelete="CASCADE"), index=True)
    registration_id: Mapped[int | None] = mapped_column(ForeignKey("client_registrations.id", ondelete="SET NULL"), index=True)
    title: Mapped[str] = mapped_column(String(200), nullable=False, index=True)
    category: Mapped[str] = mapped_column(String(60), nullable=False, default="government_portal", index=True)
    portal_url: Mapped[str | None] = mapped_column(String(800))
    reference_number: Mapped[str | None] = mapped_column(String(160), index=True)
    username_encrypted: Mapped[str | None] = mapped_column(Text)
    secret_encrypted: Mapped[str] = mapped_column(Text, nullable=False)
    additional_secret_encrypted: Mapped[str | None] = mapped_column(Text)
    notes_encrypted: Mapped[str | None] = mapped_column(Text)
    encryption_version: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
    sensitivity: Mapped[str] = mapped_column(String(30), nullable=False, default="high")
    status: Mapped[str] = mapped_column(String(30), nullable=False, default="active", index=True)
    expires_on: Mapped[date | None] = mapped_column(Date, index=True)
    rotation_due_on: Mapped[date | None] = mapped_column(Date, index=True)
    owner_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), index=True)
    allowed_user_ids_csv: Mapped[str | None] = mapped_column(Text)
    reveal_requires_reason: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    last_rotated_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    archived_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
    created_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"))
    updated_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"))
    created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, default=utcnow)
    updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, default=utcnow, onupdate=utcnow)


class CredentialVaultVersion(CommonBase):
    __tablename__ = "credential_vault_versions"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    entry_id: Mapped[int] = mapped_column(ForeignKey("credential_vault_entries.id", ondelete="CASCADE"), nullable=False, index=True)
    version_number: Mapped[int] = mapped_column(Integer, nullable=False)
    username_encrypted: Mapped[str | None] = mapped_column(Text)
    secret_encrypted: Mapped[str] = mapped_column(Text, nullable=False)
    additional_secret_encrypted: Mapped[str | None] = mapped_column(Text)
    notes_encrypted: Mapped[str | None] = mapped_column(Text)
    change_reason: Mapped[str] = mapped_column(Text, nullable=False)
    changed_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"))
    changed_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, default=utcnow)


class CredentialVaultAccessLog(CommonBase):
    __tablename__ = "credential_vault_access_logs"

    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
    branch_id: Mapped[int | None] = mapped_column(ForeignKey("branches.id", ondelete="SET NULL"), index=True)
    entry_id: Mapped[int | None] = mapped_column(ForeignKey("credential_vault_entries.id", ondelete="SET NULL"), index=True)
    actor_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), index=True)
    action: Mapped[str] = mapped_column(String(40), nullable=False, index=True)
    reason: Mapped[str | None] = mapped_column(Text)
    fields_accessed_csv: Mapped[str | None] = mapped_column(String(300))
    success: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    ip_address: Mapped[str | None] = mapped_column(String(100))
    user_agent: Mapped[str | None] = mapped_column(String(500))
    created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, default=utcnow, index=True)
