from datetime import datetime
from typing import Optional, List
from fastapi.param_functions import Query
from pydantic.networks import EmailStr
from pydantic import Field, BaseModel, ConfigDict, field_validator
from src.apps.files.schemas.file_common import FileResponseSchema
from src.apps.base.schemas.common import BaseSchema, AddressCreateRequestSchema, AddressSchema


# Shared properties
class CustomerContactBase(BaseSchema):
    model_config = ConfigDict(from_attributes=True)
    
    # Name fields - new approach
    first_name: Optional[str] = Field(
        default=None,
        description="First name of Contact"
    )
    last_name: Optional[str] = Field(
        default=None,
        description="Last name of Contact"
    )
    
    # Title and designation
    title: Optional[str] = Field(
        default=None,
        description="Title of the contact"
    )
    designation: Optional[str] = Field(
        default=None,
        description="Designation of contact (legacy field)"
    )
    relation: Optional[str] = Field(
        default=None,
        description="Relation of contact, inclusive of alphabetical characters only"
    )
    
    # Email field - now required in create schema
    email: Optional[EmailStr] = Field(default=None, description="A valid email address")
    
    # Phone fields
    phone: Optional[str] = Field(default=None, description="Personal phone number")
    account_phone: Optional[str] = Field(default=None, description="Account phone number")
    office_phone: Optional[str] = Field(default=None, description="Office phone number")
    
    # Website fields
    website: Optional[str] = Field(default=None, description="Website of the customer contact (legacy field)")
    account_website: Optional[str] = Field(default=None, description="Account website URL")
    
    # Date of birth with mm/dd/yyyy format
    dob: Optional[datetime] = Field(default=None, description="Date of birth (mm/dd/yyyy format)")
    
    tilled_id: Optional[str] = Field(
        default=None,
        description="Tilled account id of the Customer Contact"
    )
    is_active: Optional[bool] = Field(
        default=None,
        description="Activation status of Customer, false denotes that the Customer is inactive"
    )
    timezone: Optional[str] = Field(
        default=None,
        description="Selected timezone of the customer contact"
    )


class CustomerContactSchema(CustomerContactBase):
    model_config = ConfigDict(
        from_attributes=True,
        json_schema_extra={
            "example": {
                "id": 789,
                "contact_id": "con_abcd1234efgh5678",
                "first_name": "Sarah",
                "last_name": "Wilson",
                "email": "sarah.wilson@example.com",
                "account_phone": "+1555789012",
                "title": "Project Manager",
                "account_website": "https://sarahwilson.example.com",
                "dob": "1988-03-10T00:00:00Z",
                "relation": "primary",
                "timezone": "America/Denver",
                "is_active": True,
                "created_at": "2024-01-10T08:20:00Z",
                "updated_at": "2024-01-15T12:35:00Z",
                "addresses": [
                    {
                        "id": 2,
                        "address_line_1": "456 Contact Street",
                        "address_line_2": "Building C",
                        "city": "Denver",
                        "state": "CO",
                        "zipcode": "80202",
                        "country": "US",
                        "address_type": "mailing",
                        "use_as_default": False,
                        "is_active": True
                    }
                ]
            }
        }
    )
    
    id: int = Field(description="Id of Customer resource")
    contact_id: Optional[str] = Field(
        default=None,
        description="Unique id of Contact, typically of the form con_xxxx"
    )
    is_active: Optional[bool] = Field(
        default=None,
        description="Activation status of Customer, false denotes that the Customer is inactive"
    )
    created_at: Optional[datetime] = Field(
        default=None,
        description="Created date and time as unix timestamp"
    )
    updated_at: Optional[datetime] = Field(
        default=None,
        description="Updated date and time as unix timestamp"
    )
    deleted_at: Optional[datetime] = Field(
        default=None,
        description="Deleted date and time as unix timestamp"
    )
    avatar: Optional[FileResponseSchema] = Field(
        default=None,
        description="Profile picture / avatar of contact"
    )
    addresses: Optional[List[AddressSchema]] = Field(
        default=None,
        description="Customer's available addresses list"
    )


class CustomerContactCreateRequestSchema(CustomerContactBase):
    model_config = ConfigDict(
        from_attributes=True,
        json_schema_extra={
            "example": {
                "first_name": "Michael",
                "last_name": "Hussy",
                "email": "michaelhussy@yopmail.com",
                "account_phone": "+1 871 71123",
                "title": "Head of sales",
                "account_website": "https://example.com",
                "dob": "1990-05-15T00:00:00Z"
            }
        }
    )
    
    # Required fields
    first_name: str = Field(
        description="First name of Contact (required)"
    )
    last_name: str = Field(
        description="Last name of Contact (required)"
    )
    email: EmailStr = Field(description="A valid email address (required)")
    
    # Optional fields with new structure
    account_phone: Optional[str] = Field(
        default=None,
        description="Account phone number"
    )
    title: Optional[str] = Field(
        default=None,
        description="Title of the contact"
    )
    account_website: Optional[str] = Field(
        default=None,
        description="Account website URL"
    )
    
    avatar_id: Optional[int] = Field(
        default=None,
        description="ID of Uploaded image file to be used as avatar"
    )
    address: Optional[AddressCreateRequestSchema] = Field(
        default=None,
        description="Customer's billing address"
    )
    
    @field_validator("dob", mode="before")
    @classmethod
    def validate_dob_format(cls, v):
        """Validate date of birth format (mm/dd/yyyy)."""
        if v is None:
            return v
        
        if isinstance(v, str):
            try:
                # Try parsing mm/dd/yyyy format
                parsed_date = datetime.strptime(v, "%m/%d/%Y")
                return parsed_date
            except ValueError:
                try:
                    # Also allow ISO format for flexibility
                    if 'T' in v:
                        parsed_date = datetime.fromisoformat(v.replace('Z', '+00:00'))
                    else:
                        parsed_date = datetime.fromisoformat(v)
                    return parsed_date
                except ValueError:
                    raise ValueError("DOB must be in mm/dd/yyyy format or valid ISO format")
        
        return v


class CustomerContactUpdateRequestSchema(CustomerContactBase):
    model_config = ConfigDict(
        from_attributes=True,
        json_schema_extra={
            "example": {
                "first_name": "Updated Jane",
                "last_name": "Updated Smith",
                "email": "updated.jane@example.com",
                "account_phone": "+1555987654",
                "title": "Senior Account Manager",
                "account_website": "https://updated-example.com",
                "dob": "1985-12-25T00:00:00Z",
                "is_active": False,
                "timezone": "America/Chicago",
                "relation": "secondary",
                "address": {
                    "address_line_1": "789 Updated Boulevard",
                    "address_line_2": "Unit 200",
                    "zipcode": "60601",
                    "city": "Chicago",
                    "state": "IL",
                    "country": "US",
                    "address_type": "mailing",
                    "use_as_default": True
                }
            }
        }
    )
    
    is_active: Optional[bool] = Field(
        default=None,
        description="Activation status of Customer, false denotes that the Customer is inactive"
    )
    avatar_id: Optional[int] = Field(
        default=None,
        description="ID of Uploaded image file to be used as avatar"
    )
    address: Optional[AddressCreateRequestSchema] = Field(
        default=None,
        description="Customer's billing address"
    )


class CustomerContactListFilterSchema(BaseModel):
    search: Optional[str] = Query(
        default=None,
        description="Search by customer Contact name, email, transaction billing address, etc",
    )
