"""project_storage domain — SQLAlchemy models.

Core owns:
- Bucket definitions (name, access policy, RLS flag, CDN config, limits)
- Running storage usage counters per project

Cloud owns cloud_files (the actual file records) and enforces access policies.
Core never reads or writes cloud_files directly.
"""
from __future__ import annotations

import enum
from datetime import datetime
from typing import Optional
from uuid import UUID, uuid4

from sqlalchemy import BigInteger, Boolean, ForeignKey, Integer, String, Text, UniqueConstraint
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.dialects.postgresql import UUID as PGUUID
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.sql import func
from sqlalchemy.types import DateTime

from src.core.database import Base


class BucketAccessPolicy(str, enum.Enum):
    public = "public"            # CDN-served, no auth required
    private = "private"          # presigned URL only
    authenticated = "authenticated"  # valid app JWT required + optional RLS


class ProjectStorageBucket(Base):
    """Named storage bucket definition for a project.

    One row per bucket. Pushed to Cloud via control plane on every mutation.
    Cloud enforces the access policy and RLS during file operations.
    """

    __tablename__ = "project_storage_buckets"

    id: Mapped[UUID] = mapped_column(PGUUID(as_uuid=True), primary_key=True, default=uuid4)
    project_id: Mapped[UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("projects.id", ondelete="CASCADE"),
        nullable=False,
    )
    name: Mapped[str] = mapped_column(String(64), nullable=False)
    access_policy: Mapped[str] = mapped_column(String(20), nullable=False, default="private")
    rls_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    cdn_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    cdn_custom_domain: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    # None = all mime types allowed
    allowed_mime_types_json: Mapped[Optional[list]] = mapped_column(JSONB, nullable=True)
    # None = plan default applies
    max_file_size_bytes: Mapped[Optional[int]] = mapped_column(BigInteger, nullable=True)
    is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
    )

    __table_args__ = (
        UniqueConstraint("project_id", "name", name="uq_project_storage_bucket_project_name"),
    )


class ProjectStorageUsage(Base):
    """Running storage counter per project.

    Updated atomically on every confirmed upload and delete via
    POST /v1/cloud/usage/storage (Cloud → Core).
    Used by the dashboard usage display and quota enforcement at presign time.
    """

    __tablename__ = "project_storage_usage"

    id: Mapped[UUID] = mapped_column(PGUUID(as_uuid=True), primary_key=True, default=uuid4)
    project_id: Mapped[UUID] = mapped_column(
        PGUUID(as_uuid=True),
        ForeignKey("projects.id", ondelete="CASCADE"),
        nullable=False,
        unique=True,
    )
    total_bytes: Mapped[int] = mapped_column(BigInteger, nullable=False, default=0)
    total_files: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
    last_updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now()
    )
