from ninja import ModelSchema, Schema
from typing import List, Optional

from submissions.models import PuzzleResponse
from submissions.schemas import SteamCollectionItemOut


class PuzzleResponseRankingOut(ModelSchema):
    class Meta:
        model = PuzzleResponse
        fields = [
            "id",
            "puzzle_name",
            "created_at",
            "updated_at",
        ]

    points: int | None = None
    rank_points: int | None = None
    puzzle_user_rank: int
    user_response_rank: int

    user_id: int

    final_cost: int | None
    final_cycles: int | None
    final_area: int | None

    @staticmethod
    def resolve_user_id(obj) -> int:
        return obj.submission.user.id


class UserDisplayOut(Schema):
    id: int
    username: str
    is_staff: bool


class RankingSchema(Schema):
    users: list[UserDisplayOut]
    puzzles: list[SteamCollectionItemOut]
    responses_by_userid: dict[int, list[PuzzleResponseRankingOut]]
    ranking_by_puzzle: dict[int, list[PuzzleResponseRankingOut]]


class WinnerFileOut(Schema):
    """Schema for winner submission file"""

    file_url: str
    original_filename: str


class WinnerResponseOut(Schema):
    """Schema for winner response with files"""

    user_id: int
    username: str
    final_cost: Optional[int]
    final_cycles: Optional[int]
    final_area: Optional[int]
    rank_points: Optional[int]
    total_coef: Optional[int]
    files: List[WinnerFileOut]


class PuzzleSubmissionsOut(Schema):
    """Schema for puzzle with all top submissions"""

    puzzle_id: int
    puzzle_title: str
    submissions: List[WinnerResponseOut]


class TournamentSubmissionsOut(Schema):
    """Schema for tournament top submissions results"""

    submissions: List[PuzzleSubmissionsOut]


class PuzzlePointsFactorOut(Schema):
    """Schema for puzzle points factor"""

    cost: int
    cycles: int
    area: int


class PuzzleSubmissionWithRankOut(Schema):
    """Schema for puzzle submission with rank"""

    rank: int
    user_id: int
    username: str
    final_cost: Optional[int]
    final_cycles: Optional[int]
    final_area: Optional[int]
    rank_points: Optional[int]
    total_coef: Optional[int]
    files: List[WinnerFileOut]


class PuzzleResultsOut(Schema):
    """Schema for puzzle-specific results with coefficients"""

    puzzle_id: int
    puzzle_title: str
    points_factor: Optional[PuzzlePointsFactorOut]
    submissions: List[PuzzleSubmissionWithRankOut]


class TournamentPuzzleResultsOut(Schema):
    """Schema for tournament puzzle-specific results"""

    results: List[PuzzleResultsOut]
