from datetime import datetime
from typing import Annotated, Optional, List, Dict, Any
from uuid import UUID

from django.urls import reverse
from ninja import Field, FilterSchema, FilterLookup, Schema


# Filter schema for query parameters
class ReviewStatusFilter(FilterSchema):
    """Filter schema for review_status query parameter."""

    review_status: Annotated[Optional[bool], FilterLookup("package__reviewed")] = None


class SelfReviewStatusFilter(FilterSchema):
    """Filter schema for review_status query parameter on self-reviewed entities."""

    review_status: Annotated[Optional[bool], FilterLookup("reviewed")] = None


class StructureReviewStatusFilter(FilterSchema):
    """Filter schema for review_status on structures (via compound->package)."""

    review_status: Annotated[Optional[bool], FilterLookup("compound__package__reviewed")] = None


# Base schema for all package-scoped entities
class PackageEntityOutSchema(Schema):
    """Base schema for entities belonging to a package."""

    uuid: UUID
    url: str = ""
    name: str
    description: str
    review_status: str = ""
    package: str = ""

    @staticmethod
    def resolve_url(obj):
        return obj.url

    @staticmethod
    def resolve_package(obj):
        return obj.package.url

    @staticmethod
    def resolve_review_status(obj):
        return "reviewed" if obj.package.reviewed else "unreviewed"


# All package-scoped entities inherit from base
class ScenarioOutSchema(PackageEntityOutSchema):
    pass


class AdditionalInformationItemSchema(Schema):
    """Schema for additional information item in scenario creation."""

    type: str
    data: Dict[str, Any]


class ScenarioCreateSchema(Schema):
    """Schema for creating a new scenario."""

    name: str
    description: str = ""
    scenario_date: str = "No date"
    scenario_type: str = "Not specified"
    additional_information: List[AdditionalInformationItemSchema] = []


class CompoundOutSchema(PackageEntityOutSchema):
    pass


class RuleOutSchema(PackageEntityOutSchema):
    pass


class ReactionOutSchema(PackageEntityOutSchema):
    pass


class PathwayOutSchema(PackageEntityOutSchema):
    pass


class ModelOutSchema(PackageEntityOutSchema):
    pass


class CompoundStructureOutSchema(PackageEntityOutSchema):
    compound: str = ""

    @staticmethod
    def resolve_compound(obj):
        return obj.compound.url

    @staticmethod
    def resolve_package(obj):
        return obj.compound.package.url

    @staticmethod
    def resolve_review_status(obj):
        return "reviewed" if obj.compound.package.reviewed else "unreviewed"


# Package is special (no package FK)
class PackageOutSchema(Schema):
    uuid: UUID
    url: str = ""
    name: str
    description: str
    review_status: str = ""

    @staticmethod
    def resolve_url(obj):
        return obj.url

    @staticmethod
    def resolve_review_status(obj):
        return "reviewed" if obj.reviewed else "unreviewed"


class SettingOutSchema(Schema):
    uuid: UUID
    url: str = ""
    name: str
    description: str


class GroupOutSchema(Schema):
    uuid: UUID
    url: str = ""
    name: str
    description: str


class SimpleUserOutSchema(Schema):
    uuid: UUID
    url: str
    name: str = Field(alias="username")


class JobLogOutSchema(Schema):
    user: SimpleUserOutSchema
    id: UUID = Field(alias="task_id")
    url: str
    name: str = Field(alias="job_name")
    created: datetime = Field(alias="created")
    status: str = Field(alias="status")
    done: Optional[datetime] = Field(None, alias="done_at")

    @staticmethod
    def resolve_url(obj):
        return reverse("job detail", kwargs={"job_uuid": obj.task_id})
