"""Assign sales territories based on geographic and firmographic data."""

from typing import Dict, Any, Optional, List
import re


# Territory definitions (customizable per org)
TERRITORY_RULES = {
    "AMER": {
        "regions": {
            "WEST": {
                "states": [
                    "CA",
                    "OR",
                    "WA",
                    "NV",
                    "AZ",
                    "UT",
                    "ID",
                    "MT",
                    "WY",
                    "CO",
                    "NM",
                    "AK",
                    "HI",
                ],
                "countries": ["US"],
                "postal_prefixes": ["9", "8"],  # US ZIP prefixes
            },
            "CENTRAL": {
                "states": [
                    "TX",
                    "OK",
                    "KS",
                    "NE",
                    "SD",
                    "ND",
                    "MN",
                    "IA",
                    "MO",
                    "AR",
                    "LA",
                    "WI",
                    "IL",
                    "IN",
                    "MI",
                    "OH",
                ],
                "countries": ["US"],
                "postal_prefixes": ["7", "6", "5", "4"],
            },
            "EAST": {
                "states": [
                    "NY",
                    "NJ",
                    "PA",
                    "CT",
                    "RI",
                    "MA",
                    "VT",
                    "NH",
                    "ME",
                    "DE",
                    "MD",
                    "DC",
                    "VA",
                    "WV",
                    "NC",
                    "SC",
                    "GA",
                    "FL",
                    "AL",
                    "MS",
                    "TN",
                    "KY",
                ],
                "countries": ["US"],
                "postal_prefixes": ["0", "1", "2", "3"],
            },
            "CANADA": {
                "states": [],  # Use provinces
                "countries": ["CA", "CANADA"],
                "provinces": [
                    "ON",
                    "QC",
                    "BC",
                    "AB",
                    "MB",
                    "SK",
                    "NS",
                    "NB",
                    "NL",
                    "PE",
                    "NT",
                    "YT",
                    "NU",
                ],
            },
            "LATAM": {
                "countries": [
                    "MX",
                    "BR",
                    "AR",
                    "CL",
                    "CO",
                    "PE",
                    "VE",
                    "EC",
                    "BO",
                    "PY",
                    "UY",
                    "GY",
                    "SR",
                    "GF",
                ]
            },
        }
    },
    "EMEA": {
        "regions": {
            "UK_IE": {"countries": ["GB", "UK", "IE", "IRELAND"]},
            "DACH": {
                "countries": ["DE", "AT", "CH", "GERMANY", "AUSTRIA", "SWITZERLAND"]
            },
            "NORDIC": {
                "countries": [
                    "SE",
                    "NO",
                    "DK",
                    "FI",
                    "IS",
                    "SWEDEN",
                    "NORWAY",
                    "DENMARK",
                    "FINLAND",
                    "ICELAND",
                ]
            },
            "SOUTHERN_EUROPE": {
                "countries": [
                    "FR",
                    "IT",
                    "ES",
                    "PT",
                    "GR",
                    "FRANCE",
                    "ITALY",
                    "SPAIN",
                    "PORTUGAL",
                    "GREECE",
                ]
            },
            "EASTERN_EUROPE": {
                "countries": [
                    "PL",
                    "CZ",
                    "SK",
                    "HU",
                    "RO",
                    "BG",
                    "HR",
                    "SI",
                    "RS",
                    "UA",
                    "BY",
                    "RU",
                ]
            },
            "MIDDLE_EAST": {
                "countries": [
                    "AE",
                    "SA",
                    "IL",
                    "TR",
                    "EG",
                    "JO",
                    "LB",
                    "KW",
                    "QA",
                    "BH",
                    "OM",
                ]
            },
            "AFRICA": {
                "countries": [
                    "ZA",
                    "NG",
                    "KE",
                    "GH",
                    "ET",
                    "UG",
                    "TZ",
                    "EG",
                    "MA",
                    "DZ",
                ]
            },
        }
    },
    "APAC": {
        "regions": {
            "ANZ": {"countries": ["AU", "NZ", "AUSTRALIA", "NEW ZEALAND"]},
            "JAPAN": {"countries": ["JP", "JAPAN"]},
            "GREATER_CHINA": {
                "countries": [
                    "CN",
                    "HK",
                    "TW",
                    "MO",
                    "CHINA",
                    "HONG KONG",
                    "TAIWAN",
                    "MACAU",
                ]
            },
            "SOUTHEAST_ASIA": {
                "countries": [
                    "SG",
                    "MY",
                    "TH",
                    "ID",
                    "PH",
                    "VN",
                    "MM",
                    "KH",
                    "LA",
                    "SINGAPORE",
                    "MALAYSIA",
                    "THAILAND",
                    "INDONESIA",
                    "PHILIPPINES",
                    "VIETNAM",
                ]
            },
            "SOUTH_ASIA": {
                "countries": [
                    "IN",
                    "PK",
                    "BD",
                    "LK",
                    "NP",
                    "INDIA",
                    "PAKISTAN",
                    "BANGLADESH",
                    "SRI LANKA",
                    "NEPAL",
                ]
            },
            "KOREA": {"countries": ["KR", "SOUTH KOREA", "KOREA"]},
        }
    },
}

# Named account overrides (enterprise accounts with dedicated reps)
NAMED_ACCOUNTS = {
    # Example: "microsoft.com": {"territory": "GLOBAL_ACCOUNTS", "rep": "john.smith"}
}

# Company size tiers for territory assignment
SIZE_BASED_RULES = {
    "ENTERPRISE": {  # 1000+ employees
        "min_employees": 1000,
        "territory_suffix": "_ENT",
        "requires_specialty": True,
    },
    "MID_MARKET": {  # 201-999 employees
        "min_employees": 201,
        "territory_suffix": "_MM",
        "requires_specialty": False,
    },
    "SMB": {  # 51-200 employees
        "min_employees": 51,
        "territory_suffix": "_SMB",
        "requires_specialty": False,
    },
    "VELOCITY": {  # <51 employees
        "min_employees": 0,
        "territory_suffix": "_VEL",
        "requires_specialty": False,
    },
}

# Industry-specific territory assignments
VERTICAL_TERRITORIES = {
    "financial_services": "FINSERV",
    "healthcare": "HEALTHCARE",
    "government": "SLED",  # State, Local, Education
    "federal": "FEDERAL",
    "education": "EDU",
}


def assign_territory(data: Dict[str, Any]) -> Dict[str, Any]:
    """
    Assign sales territory based on location, company size, and other factors.

    Input data:
    {
        "country": "US",
        "state": "CA",
        "postal_code": "94105",
        "city": "San Francisco",
        "company_size": 500,
        "industry": "Software",
        "company_domain": "acme.com",
        "annual_revenue": 50000000
    }

    Returns:
    {
        "value": "AMER_WEST_MM",
        "components": {
            "geo": "AMER_WEST",
            "segment": "MID_MARKET",
            "vertical": null
        },
        "assignment_reason": "Geographic + Size-based assignment",
        "rep_pool": "mid_market_west",
        "priority": "standard",
        "routing_rules": ["round_robin", "capacity_based"]
    }
    """
    if not data:
        return {"value": None, "reason": "no_data"}

    # Check for named account first
    domain = data.get("company_domain", "").lower()
    if domain in NAMED_ACCOUNTS:
        named = NAMED_ACCOUNTS[domain]
        return {
            "value": named.get("territory", "NAMED_ACCOUNTS"),
            "components": {"geo": "GLOBAL", "segment": "NAMED", "vertical": None},
            "assignment_reason": "Named account",
            "assigned_rep": named.get("rep"),
            "priority": "high",
            "routing_rules": ["dedicated_rep"],
        }

    # Extract location data
    country = str(data.get("country", "")).upper()
    state = str(data.get("state", "")).upper()
    postal_code = str(data.get("postal_code", ""))
    city = str(data.get("city", "")).lower()

    # Determine geographic territory
    geo_territory = _determine_geo_territory(country, state, postal_code, city)

    # Determine size-based segment
    company_size = _parse_company_size(data.get("company_size"))
    size_segment = _determine_size_segment(company_size, data.get("annual_revenue"))

    # Check for vertical-specific territory
    industry = str(data.get("industry", "")).lower()
    vertical_territory = _determine_vertical_territory(industry)

    # Build final territory code
    components = {
        "geo": geo_territory,
        "segment": size_segment,
        "vertical": vertical_territory,
    }

    # Construct territory name
    if vertical_territory and size_segment == "ENTERPRISE":
        # Vertical territories for enterprise accounts
        territory = f"{vertical_territory}_{geo_territory}"
        assignment_reason = "Vertical + Geographic assignment"
        rep_pool = f"{vertical_territory.lower()}_team"
    elif geo_territory and size_segment:
        # Standard geographic + size assignment
        territory = f"{geo_territory}_{size_segment}"
        assignment_reason = "Geographic + Size-based assignment"
        rep_pool = f"{size_segment.lower()}_{geo_territory.lower()}"
    elif geo_territory:
        # Geographic only
        territory = geo_territory
        assignment_reason = "Geographic assignment"
        rep_pool = f"general_{geo_territory.lower()}"
    else:
        # Fallback
        territory = "UNASSIGNED"
        assignment_reason = "Insufficient data for assignment"
        rep_pool = "unassigned_queue"

    # Determine priority
    priority = _determine_priority(
        company_size, data.get("lead_score"), vertical_territory
    )

    # Determine routing rules
    routing_rules = _determine_routing_rules(size_segment, vertical_territory, priority)

    return {
        "value": territory,
        "components": components,
        "assignment_reason": assignment_reason,
        "rep_pool": rep_pool,
        "priority": priority,
        "routing_rules": routing_rules,
        "metadata": {
            "country": country,
            "state": state,
            "company_size": company_size,
            "has_vertical": bool(vertical_territory),
        },
    }


def _determine_geo_territory(
    country: str, state: str, postal_code: str, city: str
) -> Optional[str]:
    """Determine geographic territory."""
    if not country:
        return None

    # Check each major region
    for major_region, region_data in TERRITORY_RULES.items():
        for sub_region, rules in region_data["regions"].items():
            # Country match
            if country in rules.get("countries", []):
                # For US/Canada, check state/province
                if country in ["US", "CA", "CANADA"]:
                    if state and state in rules.get("states", []) + rules.get(
                        "provinces", []
                    ):
                        return f"{major_region}_{sub_region}"
                    # Check postal code prefix for US
                    if country == "US" and postal_code:
                        prefix = postal_code[0]
                        if prefix in rules.get("postal_prefixes", []):
                            return f"{major_region}_{sub_region}"
                else:
                    # Non-US/Canada countries
                    return f"{major_region}_{sub_region}"

    # Define comprehensive country sets for proper classification
    EMEA_COUNTRIES = {
        "GB",
        "UK",
        "FR",
        "DE",
        "IT",
        "ES",
        "NL",
        "BE",
        "CH",
        "AT",
        "SE",
        "NO",
        "DK",
        "FI",
        "PL",
        "CZ",
        "HU",
        "RO",
        "GR",
        "PT",
        "IE",
        "ZA",
        "AE",
        "SA",
        "EG",
        "IL",
        "TR",
        "RU",
        "UA",
        "LU",
        "IS",
        "EE",
        "LV",
        "LT",
        "SK",
        "SI",
        "HR",
        "BA",
        "RS",
        "ME",
        "AL",
        "MK",
        "BG",
        "CY",
        "MT",
    }

    APAC_COUNTRIES = {
        "JP",
        "CN",
        "IN",
        "AU",
        "SG",
        "KR",
        "HK",
        "TW",
        "NZ",
        "MY",
        "TH",
        "ID",
        "PH",
        "VN",
        "BD",
        "PK",
        "LK",
    }

    AMER_COUNTRIES = {
        "US",
        "CA",
        "MX",
        "BR",
        "AR",
        "CL",
        "CO",
        "PE",
        "VE",
        "EC",
        "BO",
        "PY",
        "UY",
        "GY",
        "SR",
        "GF",
        "CR",
        "PA",
        "NI",
        "HN",
        "SV",
        "GT",
        "BZ",
        "DO",
        "HT",
        "JM",
        "CU",
    }

    # Default by country patterns - FIXED BUG: removed startswith("E")
    if country in AMER_COUNTRIES:
        return "AMER"
    elif country in EMEA_COUNTRIES:
        return "EMEA"
    elif country in APAC_COUNTRIES:
        return "APAC"

    return "GLOBAL"


def _determine_size_segment(
    employee_count: Optional[int], revenue: Optional[float]
) -> str:
    """Determine company size segment."""
    if employee_count:
        if employee_count >= 1000:
            return "ENTERPRISE"
        elif employee_count >= 201:
            return "MID_MARKET"
        elif employee_count >= 51:
            return "SMB"
        else:
            return "VELOCITY"

    # Fallback to revenue-based if available
    if revenue:
        if revenue >= 100_000_000:  # $100M+
            return "ENTERPRISE"
        elif revenue >= 10_000_000:  # $10M+
            return "MID_MARKET"
        elif revenue >= 1_000_000:  # $1M+
            return "SMB"
        else:
            return "VELOCITY"

    return "UNCLASSIFIED"


def _determine_vertical_territory(industry: str) -> Optional[str]:
    """Check for vertical/industry-specific territory."""
    if not industry:
        return None

    for vertical_key, territory in VERTICAL_TERRITORIES.items():
        if vertical_key in industry:
            return territory

    # Check for government/public sector
    if any(
        gov in industry
        for gov in ["government", "federal", "state", "municipal", "public sector"]
    ):
        if "federal" in industry:
            return "FEDERAL"
        return "SLED"

    return None


def _parse_company_size(size: Any) -> Optional[int]:
    """Parse company size to integer."""
    if isinstance(size, (int, float)):
        return int(size)

    if isinstance(size, str):
        # Extract numbers
        numbers = re.findall(r"\d+", size)
        if numbers:
            # Take the larger number if it's a range
            return max(int(n) for n in numbers)

    return None


def _determine_priority(
    size: Optional[int], lead_score: Optional[int], vertical: Optional[str]
) -> str:
    """Determine account priority."""
    if vertical in ["FEDERAL", "FINSERV", "HEALTHCARE"]:
        return "high"

    if size and size >= 1000:
        return "high"
    elif size and size >= 201:
        return "medium"

    if lead_score and lead_score >= 80:
        return "high"
    elif lead_score and lead_score >= 60:
        return "medium"

    return "standard"


def _determine_routing_rules(
    segment: str, vertical: Optional[str], priority: str
) -> List[str]:
    """Determine how to route within territory."""
    rules = []

    if vertical:
        rules.append("vertical_specialist")

    if segment == "ENTERPRISE":
        rules.append("dedicated_ae")
        rules.append("team_selling")
    elif segment == "MID_MARKET":
        rules.append("round_robin")
        rules.append("capacity_based")
    elif segment in ["SMB", "VELOCITY"]:
        rules.append("automated_assignment")
        rules.append("pooled_model")

    if priority == "high":
        rules.insert(0, "priority_routing")

    return rules[:3]  # Return top 3 rules
