from typing import Optional, Annotated
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator, BeforeValidator
from datetime import datetime

StrId = Annotated[str, BeforeValidator(str)]


class TimelogBase(BaseModel):
    job_id: str = Field(..., max_length=36)
    user_id: str = Field(..., max_length=36)
    start_time: datetime
    end_time: Optional[datetime] = None
    duration_minutes: Optional[int] = Field(None, ge=0)
    notes: Optional[str] = None

    @field_validator("notes")
    @classmethod
    def strip_notes(cls, v):
        if v is None:
            return v
        return v.strip() if v.strip() else None

    @model_validator(mode="after")
    def validate_time_range(self):
        if self.end_time and self.start_time and self.end_time < self.start_time:
            raise ValueError("end_time must be after start_time")
        if self.duration_minutes is not None and self.duration_minutes < 0:
            raise ValueError("duration_minutes must be non-negative")
        if self.duration_minutes is not None and self.duration_minutes > 1440:
            raise ValueError("duration_minutes cannot exceed 24 hours (1440 minutes)")
        return self


class TimelogCreate(TimelogBase):
    pass


class TimelogUpdate(BaseModel):
    job_id: Optional[str] = Field(None, max_length=36)
    user_id: Optional[str] = Field(None, max_length=36)
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None
    duration_minutes: Optional[int] = Field(None, ge=0)
    notes: Optional[str] = None

    @field_validator("notes")
    @classmethod
    def strip_notes(cls, v):
        if v is None:
            return v
        return v.strip() if v.strip() else None

    @model_validator(mode="after")
    def validate_time_range(self):
        if self.end_time and self.start_time and self.end_time < self.start_time:
            raise ValueError("end_time must be after start_time")
        if self.duration_minutes is not None and self.duration_minutes < 0:
            raise ValueError("duration_minutes must be non-negative")
        if self.duration_minutes is not None and self.duration_minutes > 1440:
            raise ValueError("duration_minutes cannot exceed 24 hours (1440 minutes)")
        return self

    model_config = ConfigDict(from_attributes=True)


class TimelogResponse(BaseModel):
    id: StrId
    job_id: StrId
    user_id: StrId
    start_time: datetime
    end_time: Optional[datetime]
    duration_minutes: Optional[int]
    notes: Optional[str]
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class TimelogListResponse(BaseModel):
    items: list[TimelogResponse]
    total: int
    limit: int
    offset: int

    model_config = ConfigDict(from_attributes=True)


class TimelogStartRequest(BaseModel):
    job_id: str = Field(..., max_length=36)
    notes: Optional[str] = None

    @field_validator("notes")
    @classmethod
    def strip_notes(cls, v):
        if v is None:
            return v
        return v.strip() if v.strip() else None


class TimelogStopRequest(BaseModel):
    notes: Optional[str] = None

    @field_validator("notes")
    @classmethod
    def strip_notes(cls, v):
        if v is None:
            return v
        return v.strip() if v.strip() else None