from pydantic import BaseModel, field_validator
from typing import Optional, Dict, List, Union


class MatchResult(BaseModel):
    field_name: str
    provided_value: str
    found_in_document: Optional[str] = None
    is_match: bool
    confidence: str
    
    @field_validator('field_name', 'provided_value', 'confidence')
    @classmethod
    def validate_strings(cls, v):
        """Ensure string fields are never None"""
        if v is None:
            return ""
        return str(v)
    
    @field_validator('found_in_document', mode='before')
    @classmethod
    def convert_found_in_document(cls, v):
        """Convert numeric values to strings (LLM sometimes returns numbers unquoted)"""
        if v is None:
            return None
        # Convert any numeric type (int, float) to string
        if isinstance(v, (int, float)):
            return str(v)
        return v
    
    class Config:
        # Ensure we handle None values properly
        validate_assignment = True


class AddressMatchResponse(BaseModel):
    success: bool
    message: str
    file_url: Optional[str] = None
    analysis_results: Optional[List[MatchResult]] = []
    overall_match: Optional[bool] = None
    mismatch_details: Optional[List[str]] = []
    is_hazy: Optional[bool] = None
    document_type_detected: Optional[str] = None
    bank_statement_results: Optional[List[Dict]] = None
    vehicle_details: Optional[Dict] = None
    aggregated_months_covered: Optional[List[str]] = None
    aggregated_missing_months: Optional[List[str]] = None
    aggregated_months_complete: Optional[bool] = None
    original_file_urls: Optional[List[str]] = None
    feedback: Optional[Dict[str, List[str]]] = None  # {'fully_matched': [...], 'partially_matched': [...], 'not_matched': [...]} only populated for /verify-documents
    per_file_results: Optional[List[Dict]] = None  # For non-bank multi-file: [{'file_url': str, 'analysis_results': [...], 'mismatch_details': [...], 'overall_match': bool, 'is_hazy': bool, 'document_type_detected': str}]
    feedback_details: Optional[List[Dict[str, str]]] = None  # list of {field, status, explanation}
    feedback_text: Optional[str] = None  # simple human readable summary for single or multi file
    overall_feedback_text: Optional[str] = None  # aggregated human readable summary (multi-file)
    timestamp: str
    
    class Config:
        json_schema_extra = {
            "example": {
                "success": True,
                "message": "Name and address verification completed",
                "file_url": "http://localhost:8000/uploads/file123.jpg",
                "analysis_results": [
                    {
                        "field_name": "first_name",
                        "provided_value": "John",
                        "found_in_document": "John",
                        "is_match": True,
                        "confidence": "high"
                    },
                    {
                        "field_name": "city",
                        "provided_value": "Dummy City",
                        "found_in_document": "Dummy City",
                        "is_match": True,
                        "confidence": "high"
                    }
                ],
                "overall_match": True,
                "mismatch_details": [],
                "is_hazy": False,
                "document_type_detected": "US Driver License",
                "bank_statement_results": [
                    {
                        "file_url": "https://example.com/stmt1.png",
                        "months_covered": ["2025-05", "2025-06", "2025-07", "2025-08", "2025-09", "2025-10"],
                        "missing_months": [],
                        "balances": [
                            {"month": "2025-05", "opening_balance": "5000.00", "closing_balance": "5100.00"}
                        ],
                        "provided_final_balance": "5234.87",
                        "statement_final_balance": "5234.87",
                        "final_balance_matches": True,
                        "months_complete": True,
                        "account_holder_name_matches": True,
                        "bank_name_matches": True,
                        "account_type_matches": True,
                        "errors": []
                    }
                ],
                "aggregated_months_covered": ["2025-05", "2025-06", "2025-07", "2025-08", "2025-09", "2025-10"],
                "aggregated_missing_months": [],
                "aggregated_months_complete": True,
                "original_file_urls": [
                    "https://example.com/stmt1.png",
                    "https://example.com/stmt2.png"
                ],
                "feedback": {
                    "fully_matched": ["first_name", "last_name", "city"],
                    "partially_matched": ["street_name"],
                    "not_matched": ["middle_name"]
                },
                "feedback_details": [
                    {"field": "first_name", "status": "fully_matched", "explanation": "Exact name 'John' found on document."},
                    {"field": "street_name", "status": "partially_matched", "explanation": "Street differs slightly (provided 'Street 7' vs found 'St 7')."},
                    {"field": "middle_name", "status": "not_matched", "explanation": "Middle name not present on document."}
                ],
                "per_file_results": [
                    {
                        "file_url": "https://example.com/doc1.jpg",
                        "analysis_results": [
                            {"field_name": "first_name", "provided_value": "John", "found_in_document": "John", "is_match": True, "confidence": "high"}
                        ],
                        "mismatch_details": [],
                        "overall_match": True,
                        "is_hazy": False,
                        "document_type_detected": "US Driver License"
                    }
                ],
                "timestamp": "2025-11-07T10:30:00"
            }
        }


class ErrorResponse(BaseModel):
    success: bool = False
    message: str
    file_url: Optional[str] = None
    error_details: Optional[str] = None
    timestamp: str
