"""Competition & Event Management aggregates — Phase 9.7."""
from __future__ import annotations

import uuid
from datetime import date, datetime

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

from app.core.database import Base
from app.models.base import (
    ActorAuditMixin,
    OptimisticLockMixin,
    SoftDeleteMixin,
    TenantMixin,
    TimestampMixin,
    UUIDPrimaryKeyMixin,
)
from app.models.types import (
    CompetitionKind,
    CompetitionStatus,
    GUID,
    MatchStatus,
    MedalKind,
    RegistrationStatus,
    ResultOutcome,
)


class Competition(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
    OptimisticLockMixin,
):
    __tablename__ = "competitions"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    competition_kind: Mapped[CompetitionKind] = mapped_column(
        default=CompetitionKind.TOURNAMENT, nullable=False
    )
    sport_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    facility_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    status: Mapped[CompetitionStatus] = mapped_column(
        default=CompetitionStatus.DRAFT, nullable=False
    )
    starts_on: Mapped[date | None] = mapped_column(Date, nullable=True)
    ends_on: Mapped[date | None] = mapped_column(Date, nullable=True)
    max_teams: Mapped[int | None] = mapped_column(Integer, nullable=True)
    rules: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        UniqueConstraint(
            "tenant_id", "sports_center_id", "code", name="uq_competitions_tenant_code"
        ),
        Index("ix_competitions_center", "tenant_id", "sports_center_id"),
        Index("ix_competitions_tenant_status", "tenant_id", "status"),
        Index("ix_competitions_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionTeam(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_teams"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    captain_member_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    group_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        UniqueConstraint(
            "tenant_id",
            "competition_id",
            "code",
            name="uq_competition_teams_tenant_code",
        ),
        Index("ix_competition_teams_competition", "tenant_id", "competition_id"),
        Index("ix_competition_teams_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionGroup(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_groups"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    sort_order: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        UniqueConstraint(
            "tenant_id",
            "competition_id",
            "code",
            name="uq_competition_groups_tenant_code",
        ),
        Index("ix_competition_groups_competition", "tenant_id", "competition_id"),
        Index("ix_competition_groups_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionRegistration(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_registrations"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    member_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    team_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    status: Mapped[RegistrationStatus] = mapped_column(
        default=RegistrationStatus.PENDING, nullable=False
    )
    registered_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)

    __table_args__ = (
        Index("ix_competition_registrations_competition", "tenant_id", "competition_id"),
        Index("ix_competition_registrations_member", "tenant_id", "member_id"),
        Index("ix_competition_registrations_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionMatch(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
    OptimisticLockMixin,
):
    __tablename__ = "competition_matches"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    group_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    home_team_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    away_team_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    facility_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    scheduled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
    status: Mapped[MatchStatus] = mapped_column(
        default=MatchStatus.SCHEDULED, nullable=False
    )
    round_number: Mapped[int | None] = mapped_column(Integer, nullable=True)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        UniqueConstraint(
            "tenant_id",
            "competition_id",
            "code",
            name="uq_competition_matches_tenant_code",
        ),
        Index("ix_competition_matches_competition", "tenant_id", "competition_id"),
        Index("ix_competition_matches_scheduled", "tenant_id", "scheduled_at"),
        Index("ix_competition_matches_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionResult(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_results"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    match_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    home_score: Mapped[float | None] = mapped_column(Numeric(12, 4), nullable=True)
    away_score: Mapped[float | None] = mapped_column(Numeric(12, 4), nullable=True)
    winner_team_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    outcome: Mapped[ResultOutcome] = mapped_column(nullable=False)
    recorded_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)

    __table_args__ = (
        Index("ix_competition_results_match", "tenant_id", "match_id"),
        Index("ix_competition_results_competition", "tenant_id", "competition_id"),
        Index("ix_competition_results_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionRanking(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_rankings"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    team_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    member_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    rank: Mapped[int] = mapped_column(Integer, nullable=False)
    points: Mapped[float] = mapped_column(Numeric(12, 4), default=0, nullable=False)
    wins: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    losses: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    draws: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        Index("ix_competition_rankings_competition", "tenant_id", "competition_id"),
        Index("ix_competition_rankings_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionMedal(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_medals"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    member_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    team_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    medal_kind: Mapped[MedalKind] = mapped_column(nullable=False)
    awarded_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)

    __table_args__ = (
        Index("ix_competition_medals_competition", "tenant_id", "competition_id"),
        Index("ix_competition_medals_member", "tenant_id", "member_id"),
        Index("ix_competition_medals_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionJudge(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_judges"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    coach_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    role: Mapped[str] = mapped_column(String(100), nullable=False)
    match_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)

    __table_args__ = (
        Index("ix_competition_judges_competition", "tenant_id", "competition_id"),
        Index("ix_competition_judges_coach", "tenant_id", "coach_id"),
        Index("ix_competition_judges_tenant_deleted", "tenant_id", "is_deleted"),
    )


class CompetitionCertificate(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "competition_certificates"

    sports_center_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    competition_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    member_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    title: Mapped[str] = mapped_column(String(255), nullable=False)
    file_ref: Mapped[str | None] = mapped_column(String(255), nullable=True)
    issued_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)

    __table_args__ = (
        Index("ix_competition_certificates_competition", "tenant_id", "competition_id"),
        Index("ix_competition_certificates_member", "tenant_id", "member_id"),
        Index("ix_competition_certificates_tenant_deleted", "tenant_id", "is_deleted"),
    )
