"""Data generator for Amar domain models - can be plugged into any nest."""

import random
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional


class AmarDataGenerator:
    """Generates realistic test data for Amar domain models."""

    # Sample data pools
    FIRST_NAMES = ["Lucas", "María", "Juan", "Carolina", "Diego", "Valentina", "Martín", "Sofía", "Mateo", "Emma"]
    LAST_NAMES = ["González", "Rodríguez", "Pérez", "García", "Martínez", "López", "Fernández", "Sánchez"]

    PET_NAMES = ["Luna", "Max", "Bella", "Rocky", "Coco", "Toby", "Mia", "Charlie", "Lola", "Simba"]
    PET_SPECIES = [
        {"id": 1, "name": "Perro", "code": "DOG"},
        {"id": 2, "name": "Gato", "code": "CAT"}
    ]

    NEIGHBORHOODS = [
        {"id": 1, "name": "Palermo", "has_coverage": True, "zone": "CABA"},
        {"id": 2, "name": "Recoleta", "has_coverage": True, "zone": "CABA"},
        {"id": 3, "name": "Belgrano", "has_coverage": True, "zone": "CABA"},
        {"id": 4, "name": "Caballito", "has_coverage": True, "zone": "CABA"},
        {"id": 5, "name": "Mataderos", "has_coverage": False, "zone": "CABA"},
        {"id": 6, "name": "Villa Urquiza", "has_coverage": True, "zone": "CABA"},
    ]

    SERVICE_CATEGORIES = [
        {"id": 1, "name": "Consultas", "description": "Consultas veterinarias"},
        {"id": 2, "name": "Vacunación", "description": "Vacunas y antiparasitarios"},
        {"id": 3, "name": "Estudios", "description": "Análisis y estudios clínicos"},
        {"id": 4, "name": "Videollamada", "description": "Consultas por videollamada"},
    ]

    SERVICES = [
        {"id": 1, "category_id": 1, "name": "Consulta general clínica programada", "price": 95000, "species": ["DOG", "CAT"]},
        {"id": 2, "category_id": 2, "name": "Vacuna Antirrábica", "price": 7000, "species": ["DOG", "CAT"]},
        {"id": 3, "category_id": 2, "name": "Sextuple", "price": 12000, "species": ["DOG"]},
        {"id": 4, "category_id": 2, "name": "Triple Felina", "price": 11000, "species": ["CAT"]},
        {"id": 5, "category_id": 3, "name": "Análisis de sangre", "price": 25000, "species": ["DOG", "CAT"]},
        {"id": 6, "category_id": 3, "name": "Ecografía", "price": 35000, "species": ["DOG", "CAT"]},
        {"id": 7, "category_id": 4, "name": "Consulta por videollamada", "price": 15000, "species": ["DOG", "CAT"]},
    ]

    @classmethod
    def petowner(cls, address: str = None, is_guest: bool = True, **overrides) -> Dict[str, Any]:
        """Generate a petowner.

        Args:
            address: Owner address
            is_guest: Whether this is a guest user
            **overrides: Override any fields
        """
        owner_id = overrides.get("id", random.randint(1000, 9999))
        first_name = overrides.get("first_name", random.choice(cls.FIRST_NAMES) if not is_guest else "")
        last_name = overrides.get("last_name", random.choice(cls.LAST_NAMES) if not is_guest else "")
        address = address or f"{random.choice(['Av.', 'Calle'])} {random.choice(['Corrientes', 'Santa Fe', 'Córdoba', 'Rivadavia'])} {random.randint(1000, 5000)}"

        # Determine neighborhood from address or random
        neighborhood = overrides.get("neighborhood", random.choice([n for n in cls.NEIGHBORHOODS if n["has_coverage"]]))

        data = {
            "id": owner_id,
            "first_name": first_name,
            "last_name": last_name,
            "email": f"guest_{owner_id}@amarmascotas.ar" if is_guest else f"{first_name.lower()}.{last_name.lower()}@example.com",
            "phone": f"+54911{random.randint(10000000, 99999999)}",
            "address": address,
            "neighborhood": neighborhood,
            "is_guest": is_guest,
            "created_at": datetime.now().isoformat(),
        }

        # Apply overrides
        data.update(overrides)
        return data

    @classmethod
    def pet(cls, owner_id: int, name: str = None, species: str = "DOG", age_value: int = None, age_unit: str = "years", **overrides) -> Dict[str, Any]:
        """Generate a pet.

        Args:
            owner_id: Owner ID
            name: Pet name
            species: Pet species code (DOG, CAT)
            age_value: Age value
            age_unit: Age unit (years, months)
            **overrides: Override any fields
        """
        species_data = next((s for s in cls.PET_SPECIES if s["code"] == species.upper()), cls.PET_SPECIES[0])
        age = age_value or random.randint(1, 10)
        name = name or random.choice(cls.PET_NAMES)

        data = {
            "id": random.randint(1000, 9999),
            "owner_id": owner_id,
            "name": name,
            "species": species_data,
            "age": age,
            "age_unit": age_unit,
            "age_in_months": age if age_unit == "months" else age * 12,
            "created_at": datetime.now().isoformat(),
        }

        data.update(overrides)
        return data

    @classmethod
    def cart(cls, owner_id: int, **overrides) -> Dict[str, Any]:
        """Generate an empty cart.

        Args:
            owner_id: Owner ID
            **overrides: Override any fields
        """
        cart_id = overrides.get("id", random.randint(10000, 99999))

        data = {
            "id": cart_id,
            "owner_id": owner_id,
            "items": [],
            "resume": {
                "subtotal": 0.0,
                "discounts": 0.0,
                "total": 0.0,
            },
            "resume_items": [],
            "created_at": datetime.now().isoformat(),
        }

        data.update(overrides)
        return data

    @classmethod
    def filter_services(cls, species: str = None, neighborhood_id: int = None) -> List[Dict[str, Any]]:
        """Filter services by species and neighborhood coverage.

        Args:
            species: Species code to filter by (DOG, CAT)
            neighborhood_id: Neighborhood ID for coverage check
        """
        services = cls.SERVICES.copy()

        if species:
            species_code = species.upper()
            services = [s for s in services if species_code in s["species"]]

        # Neighborhood coverage - only videollamada if no coverage
        if neighborhood_id:
            neighborhood = next((n for n in cls.NEIGHBORHOODS if n["id"] == neighborhood_id), None)
            if not neighborhood or not neighborhood.get("has_coverage"):
                services = [s for s in services if s["category_id"] == 4]  # Only videollamada

        return [
            {
                "id": s["id"],
                "name": s["name"],
                "category_id": s["category_id"],
                "price": s["price"],
                "currency": "ARS",
                "available": True,
            }
            for s in services
        ]

    @classmethod
    def filter_categories(cls, species: str = None, neighborhood_id: int = None) -> List[Dict[str, Any]]:
        """Filter categories that have available services.

        Args:
            species: Species code to filter by
            neighborhood_id: Neighborhood ID for coverage check
        """
        available_services = cls.filter_services(species, neighborhood_id)
        service_category_ids = {s["category_id"] for s in available_services}

        return [
            {
                "id": cat["id"],
                "name": cat["name"],
                "description": cat["description"],
                "service_count": len([s for s in available_services if s["category_id"] == cat["id"]]),
            }
            for cat in cls.SERVICE_CATEGORIES
            if cat["id"] in service_category_ids
        ]

    @classmethod
    def calculate_cart_summary(cls, cart: Dict[str, Any], items: List[Dict[str, Any]]) -> Dict[str, Any]:
        """Calculate cart totals with discounts and splits.

        Args:
            cart: Cart data
            items: List of cart items with price and quantity
        """
        subtotal = sum(item.get("price", 0) * item.get("quantity", 1) for item in items)

        # Multi-pet discount
        pet_count = len({item.get("pet_id") for item in items if item.get("pet_id")})
        discount_rate = 0.0
        if pet_count >= 2:
            discount_rate = 0.10  # 10% for 2+ pets

        discount_amount = subtotal * discount_rate
        total = subtotal - discount_amount

        resume_items = [
            {"concept": "SUBTOTAL", "amount": subtotal},
        ]

        if discount_amount > 0:
            resume_items.append({"concept": "DESCUENTO MULTIMASCOTA", "amount": -discount_amount})

        # Calculate vet honorarios (52% of total in real system)
        honorarios = total * 0.52
        resume_items.append({"concept": "HONORARIOS", "amount": honorarios})
        resume_items.append({"concept": "TOTAL", "amount": total})

        return {
            **cart,
            "items": items,
            "resume": {
                "subtotal": round(subtotal, 2),
                "discounts": round(discount_amount, 2),
                "total": round(total, 2),
            },
            "resume_items": resume_items,
            "updated_at": datetime.now().isoformat(),
        }

    @classmethod
    def service_request(cls, cart_id: int, requested_date: str = None, **overrides) -> Dict[str, Any]:
        """Generate a service request.

        Args:
            cart_id: Cart ID
            requested_date: ISO format date string
            **overrides: Override any fields
        """
        request_id = overrides.get("id", random.randint(100000, 999999))
        requested_date = requested_date or (datetime.now() + timedelta(days=random.randint(1, 7))).isoformat()

        data = {
            "id": request_id,
            "cart_id": cart_id,
            "requested_date": requested_date,
            "state": "PENDING",
            "veterinarian": None,
            "created_at": datetime.now().isoformat(),
        }

        data.update(overrides)
        return data
