import uuid
from datetime import datetime

from sqlalchemy import String, Integer, ForeignKey, Index, func, Text
from sqlalchemy import Uuid
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.database import Base


class Organization(Base):
    __tablename__ = "organizations"

    id: Mapped[uuid.UUID] = mapped_column(
        Uuid(as_uuid=True),
        primary_key=True,
        default=uuid.uuid4,
    )
    name: Mapped[str] = mapped_column(String(100), nullable=False)
    slug: Mapped[str] = mapped_column(String(50), unique=True, nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    logo_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
    plan: Mapped[str] = mapped_column(String(20), server_default="free", nullable=False)
    max_members: Mapped[int] = mapped_column(Integer, server_default="5", nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        server_default=func.now(),
        nullable=False,
    )
    updated_at: Mapped[datetime] = mapped_column(
        server_default=func.now(),
        onupdate=func.now(),
        nullable=False,
    )

    # Relationships
    members: Mapped[list["OrgMember"]] = relationship(
        "OrgMember", back_populates="organization", cascade="all, delete-orphan"
    )
    lifecycle_projects: Mapped[list["LifecycleProject"]] = relationship(
        "LifecycleProject", back_populates="organization", cascade="all, delete-orphan"
    )
    agents: Mapped[list["AgentTask"]] = relationship(
        "AgentTask", back_populates="organization"
    )
    contents: Mapped[list["Content"]] = relationship(
        "Content", back_populates="organization", cascade="all, delete-orphan"
    )
    brand_knowledge_entries: Mapped[list["BrandKnowledge"]] = relationship(
        "BrandKnowledge", back_populates="organization", cascade="all, delete-orphan"
    )
    knowledge_bases: Mapped[list["KnowledgeBase"]] = relationship(
        "KnowledgeBase", back_populates="organization", cascade="all, delete-orphan"
    )
    keywords: Mapped[list["Keyword"]] = relationship(
        "Keyword", back_populates="organization", cascade="all, delete-orphan"
    )
    users: Mapped[list["User"]] = relationship(
        "User", back_populates="organization"
    )

    __table_args__ = (
        Index("idx_organizations_slug", "slug"),
    )


class OrgMember(Base):
    __tablename__ = "org_members"

    id: Mapped[uuid.UUID] = mapped_column(
        Uuid(as_uuid=True),
        primary_key=True,
        default=uuid.uuid4,
    )
    organization_id: Mapped[uuid.UUID] = mapped_column(
        Uuid(as_uuid=True),
        ForeignKey("organizations.id", ondelete="CASCADE"),
        nullable=False,
    )
    user_id: Mapped[uuid.UUID] = mapped_column(
        Uuid(as_uuid=True),
        ForeignKey("users.id", ondelete="CASCADE"),
        nullable=False,
    )
    role: Mapped[str] = mapped_column(String(20), server_default="viewer", nullable=False)
    joined_at: Mapped[datetime] = mapped_column(
        server_default=func.now(),
        nullable=False,
    )
    invited_by: Mapped[uuid.UUID | None] = mapped_column(
        Uuid(as_uuid=True),
        nullable=True,
    )

    # Relationships
    organization: Mapped["Organization"] = relationship(
        "Organization", back_populates="members"
    )
    user: Mapped["User"] = relationship(
        "User", back_populates="org_memberships"
    )

    __table_args__ = (
        Index("idx_org_members_organization_id", "organization_id"),
        Index("idx_org_members_user_id", "user_id"),
        Index("idx_org_members_org_user", "organization_id", "user_id", unique=True),
    )
