# app/schemas/syndarix/sprint.py
"""
Pydantic schemas for Sprint entity.
"""

from datetime import date, datetime
from uuid import UUID

from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator

from .enums import SprintStatus


class SprintBase(BaseModel):
    """Base sprint schema with common fields."""

    name: str = Field(..., min_length=1, max_length=255)
    number: int = Field(..., ge=1)
    goal: str | None = None
    start_date: date
    end_date: date
    status: SprintStatus = SprintStatus.PLANNED
    planned_points: int | None = Field(None, ge=0)
    velocity: int | None = Field(None, ge=0)

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str) -> str:
        """Validate sprint name."""
        if not v or v.strip() == "":
            raise ValueError("Sprint name cannot be empty")
        return v.strip()

    @model_validator(mode="after")
    def validate_dates(self) -> "SprintBase":
        """Validate that end_date is after start_date."""
        if self.end_date < self.start_date:
            raise ValueError("End date must be after or equal to start date")
        return self


class SprintCreate(SprintBase):
    """Schema for creating a new sprint."""

    project_id: UUID


class SprintUpdate(BaseModel):
    """Schema for updating a sprint."""

    name: str | None = Field(None, min_length=1, max_length=255)
    goal: str | None = None
    start_date: date | None = None
    end_date: date | None = None
    status: SprintStatus | None = None
    planned_points: int | None = Field(None, ge=0)
    velocity: int | None = Field(None, ge=0)

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str | None) -> str | None:
        """Validate sprint name."""
        if v is not None and (not v or v.strip() == ""):
            raise ValueError("Sprint name cannot be empty")
        return v.strip() if v else v


class SprintStart(BaseModel):
    """Schema for starting a sprint."""

    start_date: date | None = None  # Optionally override start date


class SprintComplete(BaseModel):
    """Schema for completing a sprint."""

    velocity: int | None = Field(None, ge=0)
    notes: str | None = None


class SprintInDB(SprintBase):
    """Schema for sprint in database."""

    id: UUID
    project_id: UUID
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class SprintResponse(SprintBase):
    """Schema for sprint API responses."""

    id: UUID
    project_id: UUID
    created_at: datetime
    updated_at: datetime

    # Expanded fields from relationships
    project_name: str | None = None
    project_slug: str | None = None
    issue_count: int | None = 0
    open_issues: int | None = 0
    completed_issues: int | None = 0

    model_config = ConfigDict(from_attributes=True)


class SprintListResponse(BaseModel):
    """Schema for paginated sprint list responses."""

    sprints: list[SprintResponse]
    total: int
    page: int
    page_size: int
    pages: int


class SprintVelocity(BaseModel):
    """Schema for sprint velocity metrics."""

    sprint_number: int
    sprint_name: str
    planned_points: int | None
    velocity: int | None  # Sum of completed story points
    velocity_ratio: float | None  # velocity/planned ratio


class SprintBurndown(BaseModel):
    """Schema for sprint burndown data point."""

    date: date
    remaining_points: int
    ideal_remaining: float
