"""Outside Sales Export — county-grouped list for field visits.

Generates printable lists of leads that cannot be contacted digitally
(no usable email, no phone). Grouped by county, sorted by score.

Plain ASCII output — no unicode, no ANSI colors, safe for Word/paste/print.
"""

import csv
import io
from datetime import datetime
from typing import Optional

from state.backlog import load_backlog
from integrations.ctsos import FILING_SERVICE_DOMAINS


FREE_EMAIL_DOMAINS = {
    "gmail.com", "yahoo.com", "hotmail.com", "outlook.com", "aol.com", "icloud.com",
}

COUNTY_ORDER = [
    "new haven",
    "fairfield",
    "hartford",
]


def _is_outside_sales_lead(lead: dict) -> bool:
    """Check if a lead qualifies for outside sales.

    Criteria:
    - No usable email (empty, filing-service, or free provider)
    - No phone (phone, domain_phone, brave_phone all empty)
    - Has a physical address (street_address or city/state/zip)
    """
    email = lead.get("email", "")
    phone = lead.get("phone", "") or lead.get("domain_phone", "") or lead.get("brave_phone", "")

    if phone:
        return False

    if email and "@" in email:
        domain = email.split("@")[-1].lower().strip()
        is_filing = lead.get("email_is_filing_service", False) or domain in FILING_SERVICE_DOMAINS
        is_free = domain in FREE_EMAIL_DOMAINS
        if not is_filing and not is_free:
            return False

    has_address = bool(
        lead.get("street_address") or
        lead.get("city") or
        lead.get("zip")
    )

    return has_address


def _get_county(lead: dict) -> str:
    """Get county name from lead, normalized for grouping."""
    county = lead.get("county", "")
    if county:
        return county.strip()
    return ""


def _group_by_county(leads: list) -> list:
    """Group leads by county in display order.

    Order: New Haven, Fairfield, Hartford, other CT counties alphabetically,
    then OTHER / UNKNOWN.

    Returns list of (county_display_name, leads_list) tuples.
    """
    groups = {}
    for lead in leads:
        county = _get_county(lead)
        if county:
            key = county.lower()
            if key not in groups:
                groups[key] = (county, [])
            groups[key][1].append(lead)
        else:
            if "other" not in groups:
                groups["other"] = ("OTHER / UNKNOWN COUNTY", [])
            groups["other"][1].append(lead)

    result = []

    for order_name in COUNTY_ORDER:
        if order_name in groups:
            display_name, county_leads = groups.pop(order_name)
            county_leads.sort(key=lambda x: -x.get("score", 0))
            result.append((display_name.upper(), county_leads))

    remaining = sorted(groups.items(), key=lambda x: x[1][0])
    for key, (display_name, county_leads) in remaining:
        county_leads.sort(key=lambda x: -x.get("score", 0))
        result.append((display_name.upper(), county_leads))

    return result


def _format_address(lead: dict) -> str:
    """Format a lead's address as a single line."""
    parts = []
    if lead.get("street_address"):
        parts.append(lead["street_address"])
    city = lead.get("city", "")
    state = lead.get("state", "CT")
    zip_code = lead.get("zip", "")

    location_parts = []
    if city:
        location_parts.append(city)
    if state:
        location_parts.append(state)
    if zip_code:
        location_parts.append(zip_code)

    if location_parts:
        parts.append(" ".join(location_parts))

    return ", ".join(parts) if parts else "(no address)"


def _get_reason(lead: dict) -> str:
    """Get human-readable reason for outside sales classification."""
    email = lead.get("email", "")
    phone = lead.get("phone", "") or lead.get("domain_phone", "") or lead.get("brave_phone", "")

    reasons = []

    if not email:
        reasons.append("no email")
    elif lead.get("email_is_filing_service", False):
        reasons.append("filing service email")
    elif "@" in email:
        domain = email.split("@")[-1].lower().strip()
        if domain in FREE_EMAIL_DOMAINS:
            reasons.append("free email only")

    if not phone:
        reasons.append("no phone")

    return " ".join(reasons) if reasons else "no digital contact"


def format_txt(leads: list, county_filter: Optional[str] = None) -> str:
    """Format outside sales leads as plain ASCII text.

    Args:
        leads: List of outside sales lead dicts
        county_filter: If set, only show this county

    Returns:
        Plain ASCII string
    """
    if not leads:
        return "No outside sales leads found."

    lines = []
    today = datetime.utcnow().strftime("%Y-%m-%d")
    total = len(leads)

    if county_filter:
        lines.append(f"OUTSIDE SALES LEADS -- {county_filter} County")
        lines.append(f"Generated {today} | {total} leads")
    else:
        lines.append(f"OUTSIDE SALES LEADS -- Generated {today}")
        lines.append(f"Total: {total} leads (no usable email, no phone)")

    lines.append("=" * 60)
    lines.append("")

    grouped = _group_by_county(leads)

    if county_filter:
        filtered_grouped = []
        for display_name, county_leads in grouped:
            if county_filter.lower() in display_name.lower():
                filtered_grouped.append((display_name, county_leads))
        grouped = filtered_grouped

    global_idx = 1
    for display_name, county_leads in grouped:
        if not county_leads:
            continue

        lines.append(f"{display_name} ({len(county_leads)} leads)")
        lines.append("-" * len(f"{display_name} ({len(county_leads)} leads)"))
        lines.append("")

        for lead in county_leads:
            name = lead.get("name", "Unknown")
            address = _format_address(lead)
            filed = lead.get("filing_date", "")[:10]
            naics = (lead.get("naics", "") or "")[:50]
            score = lead.get("score", 0)
            reason = _get_reason(lead)

            lines.append(f" {global_idx:3d}. {name}")
            lines.append(f"    {address}")
            lines.append(f"    Filed: {filed} | NAICS: {naics}")
            lines.append(f"    Score: {score} | {reason}")
            lines.append("    ---")
            lines.append("")

            global_idx += 1

    lines.append("=" * 60)
    lines.append(f"END OF LIST -- {total} leads")

    return "\n".join(lines)


def format_csv(leads: list) -> str:
    """Format outside sales leads as CSV.

    Columns: county, name, address, city, state, zip, filed, naics, score, reason

    Returns:
        CSV string
    """
    output = io.StringIO()
    writer = csv.writer(output)

    writer.writerow(["county", "name", "address", "city", "state", "zip", "filed", "naics", "score", "reason"])

    for lead in leads:
        county = _get_county(lead) or "UNKNOWN"
        name = lead.get("name", "")
        street = lead.get("street_address", "")
        city = lead.get("city", "")
        state = lead.get("state", "CT")
        zip_code = lead.get("zip", "")
        filed = lead.get("filing_date", "")[:10]
        naics = (lead.get("naics", "") or "")[:50]
        score = lead.get("score", 0)
        reason = _get_reason(lead)

        writer.writerow([county, name, street, city, state, zip_code, filed, naics, score, reason])

    return output.getvalue()


def get_outside_sales_leads(county_filter: Optional[str] = None) -> list:
    """Get all leads that qualify for outside sales.

    Args:
        county_filter: If set, only return leads from this county

    Returns:
        List of lead dicts sorted by score descending
    """
    backlog = load_backlog()

    leads = [lead for lead in backlog if _is_outside_sales_lead(lead)]

    if county_filter:
        leads = [
            lead for lead in leads
            if county_filter.lower() in _get_county(lead).lower()
        ]

    leads.sort(key=lambda x: -x.get("score", 0))

    return leads
