from pydantic import BaseModel, Field, field_validator, ConfigDict
from typing import Optional
from datetime import datetime
import json


class ActivitylogBase(BaseModel):
    entity_type: str = Field(..., min_length=1, max_length=100)
    entity_id: str = Field(..., min_length=1, max_length=36)
    user_id: Optional[str] = Field(None, max_length=36)
    action_type: str = Field(..., min_length=1, max_length=100)
    details: Optional[str] = None
    ip_address: Optional[str] = Field(None, max_length=45)
    timestamp: datetime

    @field_validator("entity_type")
    @classmethod
    def validate_entity_type(cls, v: str) -> str:
        if not v or not v.strip():
            raise ValueError("entity_type cannot be empty")
        return v.strip()

    @field_validator("entity_id")
    @classmethod
    def validate_entity_id(cls, v: str) -> str:
        if not v or not v.strip():
            raise ValueError("entity_id cannot be empty")
        return v.strip()

    @field_validator("action_type")
    @classmethod
    def validate_action_type(cls, v: str) -> str:
        if not v or not v.strip():
            raise ValueError("action_type cannot be empty")
        return v.strip()

    @field_validator("details")
    @classmethod
    def validate_details_json(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and v.strip():
            try:
                json.loads(v)
            except json.JSONDecodeError:
                raise ValueError("details must be valid JSON")
        return v

    @field_validator("ip_address")
    @classmethod
    def validate_ip_address(cls, v: Optional[str]) -> Optional[str]:
        if v is not None:
            v = v.strip()
            if v:
                parts = v.split(".")
                if len(parts) == 4:
                    try:
                        for part in parts:
                            num = int(part)
                            if num < 0 or num > 255:
                                raise ValueError("Invalid IPv4 address")
                    except ValueError:
                        pass
                elif ":" not in v:
                    raise ValueError("ip_address must be a valid IPv4 or IPv6 address")
        return v


class ActivitylogCreate(ActivitylogBase):
    pass


class ActivitylogUpdate(BaseModel):
    entity_type: Optional[str] = Field(None, max_length=100)
    entity_id: Optional[str] = Field(None, max_length=36)
    user_id: Optional[str] = Field(None, max_length=36)
    action_type: Optional[str] = Field(None, max_length=100)
    details: Optional[str] = None
    ip_address: Optional[str] = Field(None, max_length=45)
    timestamp: Optional[datetime] = None

    @field_validator("entity_type")
    @classmethod
    def validate_entity_type(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and (not v or not v.strip()):
            raise ValueError("entity_type cannot be empty")
        return v.strip() if v else v

    @field_validator("entity_id")
    @classmethod
    def validate_entity_id(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and (not v or not v.strip()):
            raise ValueError("entity_id cannot be empty")
        return v.strip() if v else v

    @field_validator("action_type")
    @classmethod
    def validate_action_type(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and (not v or not v.strip()):
            raise ValueError("action_type cannot be empty")
        return v.strip() if v else v

    @field_validator("details")
    @classmethod
    def validate_details_json(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and v.strip():
            try:
                json.loads(v)
            except json.JSONDecodeError:
                raise ValueError("details must be valid JSON")
        return v

    @field_validator("ip_address")
    @classmethod
    def validate_ip_address(cls, v: Optional[str]) -> Optional[str]:
        if v is not None:
            v = v.strip()
            if v:
                parts = v.split(".")
                if len(parts) == 4:
                    try:
                        for part in parts:
                            num = int(part)
                            if num < 0 or num > 255:
                                raise ValueError("Invalid IPv4 address")
                    except ValueError:
                        pass
                elif ":" not in v:
                    raise ValueError("ip_address must be a valid IPv4 or IPv6 address")
        return v


class ActivitylogResponse(ActivitylogBase):
    id: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class UserSummary(BaseModel):
    id: str
    email: str
    first_name: str
    last_name: str

    model_config = ConfigDict(from_attributes=True)


class ActivitylogDetailResponse(ActivitylogResponse):
    user: Optional[UserSummary] = None

    model_config = ConfigDict(from_attributes=True)