from datetime import date, datetime
from typing import Optional, List, Any
from pydantic import BaseModel, ConfigDict, field_validator

# Assuming ChoreFrequencyEnum is imported from models
# Adjust the import path if necessary based on your project structure.
# e.g., from app.models import ChoreFrequencyEnum
from ..models import ChoreFrequencyEnum, ChoreTypeEnum, User as UserModel, ChoreHistoryEventTypeEnum # For UserPublic relation
from .user import UserPublic # For embedding user information

# Forward declaration for circular dependencies
class ChoreAssignmentPublic(BaseModel):
    pass

# History Schemas
class ChoreHistoryPublic(BaseModel):
    id: int
    event_type: ChoreHistoryEventTypeEnum
    event_data: Optional[dict[str, Any]] = None
    changed_by_user: Optional[UserPublic] = None
    timestamp: datetime

    model_config = ConfigDict(from_attributes=True)

class ChoreAssignmentHistoryPublic(BaseModel):
    id: int
    event_type: ChoreHistoryEventTypeEnum
    event_data: Optional[dict[str, Any]] = None
    changed_by_user: Optional[UserPublic] = None
    timestamp: datetime

    model_config = ConfigDict(from_attributes=True)


# Chore Schemas
class ChoreBase(BaseModel):
    name: str
    description: Optional[str] = None
    frequency: ChoreFrequencyEnum
    custom_interval_days: Optional[int] = None
    next_due_date: date # For creation, this will be the initial due date
    type: ChoreTypeEnum

    @field_validator('custom_interval_days', mode='before')
    @classmethod
    def check_custom_interval_days(cls, value, values):
        # Pydantic v2 uses `values.data` to get all fields
        # For older Pydantic, it might just be `values`
        # This is a simplified check; actual access might differ slightly
        # based on Pydantic version context within the validator.
        # The goal is to ensure custom_interval_days is present if frequency is 'custom'.
        # This validator might be more complex in a real Pydantic v2 setup.
        
        # A more direct way if 'frequency' is already parsed into values.data:
        # freq = values.data.get('frequency')
        # For this example, we'll assume 'frequency' might not be in 'values.data' yet
        # if 'custom_interval_days' is validated 'before' 'frequency'.
        # A truly robust validator might need to be on the whole model or run 'after'.
        # For now, this is a placeholder for the logic.
        # Consider if this validation is better handled at the service/CRUD layer for complex cases.
        return value

class ChoreCreate(ChoreBase):
    group_id: Optional[int] = None

    @field_validator('group_id')
    @classmethod
    def validate_group_id(cls, v, values):
        if values.data.get('type') == ChoreTypeEnum.group and v is None:
            raise ValueError("group_id is required for group chores")
        if values.data.get('type') == ChoreTypeEnum.personal and v is not None:
            raise ValueError("group_id must be None for personal chores")
        return v

class ChoreUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    frequency: Optional[ChoreFrequencyEnum] = None
    custom_interval_days: Optional[int] = None
    next_due_date: Optional[date] = None # Allow updating next_due_date directly if needed
    type: Optional[ChoreTypeEnum] = None
    group_id: Optional[int] = None
    # last_completed_at should generally not be updated directly by user

    @field_validator('group_id')
    @classmethod
    def validate_group_id(cls, v, values):
        if values.data.get('type') == ChoreTypeEnum.group and v is None:
            raise ValueError("group_id is required for group chores")
        if values.data.get('type') == ChoreTypeEnum.personal and v is not None:
            raise ValueError("group_id must be None for personal chores")
        return v

class ChorePublic(ChoreBase):
    id: int
    group_id: Optional[int] = None
    created_by_id: int
    last_completed_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    creator: Optional[UserPublic] = None # Embed creator UserPublic schema
    assignments: List[ChoreAssignmentPublic] = []
    history: List[ChoreHistoryPublic] = []

    model_config = ConfigDict(from_attributes=True)

# Chore Assignment Schemas
class ChoreAssignmentBase(BaseModel):
    chore_id: int
    assigned_to_user_id: int
    due_date: date

class ChoreAssignmentCreate(ChoreAssignmentBase):
    pass

class ChoreAssignmentUpdate(BaseModel):
    # Only completion status and perhaps due_date can be updated for an assignment
    is_complete: Optional[bool] = None
    due_date: Optional[date] = None # If rescheduling an existing assignment is allowed
    assigned_to_user_id: Optional[int] = None # For reassigning the chore

class ChoreAssignmentPublic(ChoreAssignmentBase):
    id: int
    is_complete: bool
    completed_at: Optional[datetime] = None
    created_at: datetime
    updated_at: datetime
    # Embed ChorePublic and UserPublic for richer responses
    chore: Optional[ChorePublic] = None
    assigned_user: Optional[UserPublic] = None
    history: List[ChoreAssignmentHistoryPublic] = []

    model_config = ConfigDict(from_attributes=True)

# To handle potential circular imports if ChorePublic needs GroupPublic and GroupPublic needs ChorePublic
# We can update forward refs after all models are defined.
ChorePublic.model_rebuild()
ChoreAssignmentPublic.model_rebuild()
