"""
Build a field marketing market finder model in Google Sheets.
"""

from __future__ import annotations

import logging
from collections import defaultdict
from typing import Any, Dict, List, Optional

logger = logging.getLogger(__name__)

ALLOWED_GEO_KEY_TYPES = {"city_state", "zip", "state", "country"}
UNKNOWN_MARKET = "(Unknown)"


def _inputs_to_dict(inputs: Any) -> Dict[str, Any]:
    if hasattr(inputs, "dict"):
        return inputs.dict()
    if isinstance(inputs, dict):
        return inputs
    return dict(inputs)


def _escape_soql_literal(value: str) -> str:
    return str(value).replace("\\", "\\\\").replace("'", "\\'")


def _normalize_values(values: Any) -> List[str]:
    if values is None:
        return []
    if isinstance(values, str):
        raw = values.split(",")
        return [v.strip() for v in raw if v and v.strip()]
    if isinstance(values, (list, tuple, set)):
        return [str(v).strip() for v in values if str(v).strip()]
    return [str(values).strip()] if str(values).strip() else []


def _build_filter_clause(field: str, values: List[str], field_type: str) -> str:
    field = str(field or "").strip()
    if not field:
        raise ValueError("Filter field is required.")

    ftype = (field_type or "picklist").strip().lower()
    if ftype == "boolean":
        flag = True
        if values:
            raw = str(values[0]).strip().lower()
            flag = raw in {"true", "1", "yes", "y", "t"}
        return f"{field} = {'TRUE' if flag else 'FALSE'}"

    if not values:
        raise ValueError(f"Filter values required for field '{field}'.")

    rendered: List[str] = []
    for val in values:
        raw = str(val).strip()
        if not raw:
            continue
        if ftype == "text":
            rendered.append(f"'{_escape_soql_literal(raw)}'")
            continue
        # Default to picklist-like behavior
        rendered.append(f"'{_escape_soql_literal(raw)}'")

    if not rendered:
        raise ValueError(f"Filter values required for field '{field}'.")

    return f"{field} IN ({', '.join(rendered)})"


def _title_case(value: str) -> str:
    return " ".join(word.capitalize() for word in str(value).strip().split())


def _format_country(value: str) -> str:
    text = str(value).strip()
    if not text:
        return ""
    if len(text) <= 3:
        return text.upper()
    return text.title()


def _normalize_geo_key(
    geo_key_type: str,
    city: Optional[str],
    state: Optional[str],
    postal: Optional[str],
    country: Optional[str],
) -> str:
    key_type = (geo_key_type or "city_state").strip().lower()
    city_val = str(city or "").strip()
    state_val = str(state or "").strip()
    postal_val = str(postal or "").strip()
    country_val = str(country or "").strip()

    if key_type == "city_state":
        if city_val and state_val:
            return f"{_title_case(city_val)}, {state_val.upper()}"
        if state_val:
            return state_val.upper()
        if city_val:
            return _title_case(city_val)
        return UNKNOWN_MARKET
    if key_type == "state":
        return state_val.upper() if state_val else UNKNOWN_MARKET
    if key_type == "zip":
        return postal_val if postal_val else UNKNOWN_MARKET
    if key_type == "country":
        return _format_country(country_val) if country_val else UNKNOWN_MARKET
    return UNKNOWN_MARKET


def _safe_float(value: Any) -> float:
    if value is None:
        return 0.0
    try:
        return float(value)
    except (TypeError, ValueError):
        return 0.0


def _col_letter(idx: int) -> str:
    result = ""
    idx_val = idx
    while True:
        idx_val, rem = divmod(idx_val, 26)
        result = chr(ord("A") + rem) + result
        if idx_val == 0:
            break
        idx_val -= 1
    return result


def _quote_tab(tab_name: str) -> str:
    """Escape single quotes in tab names for sheet references."""
    escaped = tab_name.replace("'", "''")
    return f"'{escaped}'"


def _sheet_cell(tab_name: str, cell_ref: str) -> str:
    """Build a quoted sheet cell reference."""
    return f"{_quote_tab(tab_name)}!{cell_ref}"


def _ensure_sheet(service, spreadsheet_id: str, sheet_name: str, replace: bool = False) -> int:
    try:
        ss = service.spreadsheets().get(spreadsheetId=spreadsheet_id).execute()
        for sheet in ss.get("sheets", []):
            if sheet["properties"]["title"] == sheet_name:
                if replace:
                    sheet_id = sheet["properties"]["sheetId"]
                    service.spreadsheets().batchUpdate(
                        spreadsheetId=spreadsheet_id,
                        body={"requests": [{"deleteSheet": {"sheetId": sheet_id}}]},
                    ).execute()
                    break
                return sheet["properties"]["sheetId"]
    except Exception:
        pass

    resp = service.spreadsheets().batchUpdate(
        spreadsheetId=spreadsheet_id,
        body={"requests": [{"addSheet": {"properties": {"title": sheet_name}}}]},
    ).execute()
    return resp["replies"][0]["addSheet"]["properties"]["sheetId"]


def _ensure_sheets(
    service, spreadsheet_id: str, sheet_names: List[str], replace: bool = False
) -> None:
    try:
        ss = service.spreadsheets().get(spreadsheetId=spreadsheet_id).execute()
        existing = {
            sheet["properties"]["title"]: sheet["properties"]["sheetId"]
            for sheet in ss.get("sheets", [])
        }
    except Exception:
        existing = {}

    requests: List[Dict[str, Any]] = []
    for name in sheet_names:
        if name in existing:
            if replace:
                requests.append({"deleteSheet": {"sheetId": existing[name]}})
                requests.append({"addSheet": {"properties": {"title": name}}})
        else:
            requests.append({"addSheet": {"properties": {"title": name}}})

    if requests:
        service.spreadsheets().batchUpdate(
            spreadsheetId=spreadsheet_id, body={"requests": requests}
        ).execute()


def _write_rows(service, spreadsheet_id: str, sheet_name: str, rows: List[List[Any]]) -> None:
    if not rows:
        return
    num_cols = max(len(row) for row in rows)
    end_col = _col_letter(num_cols - 1)
    range_str = f"{sheet_name}!A1:{end_col}{len(rows)}"
    padded_rows = []
    for row in rows:
        padded_rows.append(list(row) + [""] * (num_cols - len(row)))
    service.spreadsheets().values().update(
        spreadsheetId=spreadsheet_id,
        range=range_str,
        valueInputOption="USER_ENTERED",
        body={"values": padded_rows},
    ).execute()


def _validate_market_finder_inputs(values: Dict[str, Any]) -> None:
    weights = [
        float(values.get("weight_customer", 0.0)),
        float(values.get("weight_prospect", 0.0)),
        float(values.get("weight_overlap", 0.0)),
    ]
    total = sum(weights)
    if abs(total - 1.0) > 0.01:
        raise ValueError("Weights must sum to 1.0.")

    geo_key = (values.get("geo_key_type") or "city_state").strip().lower()
    if geo_key not in ALLOWED_GEO_KEY_TYPES:
        raise ValueError(f"geo_key_type must be one of {sorted(ALLOWED_GEO_KEY_TYPES)}.")


async def _fetch_records(sf_client, soql: str) -> List[Dict[str, Any]]:
    records: List[Dict[str, Any]] = []
    if hasattr(sf_client, "paginate_soql"):
        async for batch in sf_client.paginate_soql(soql):
            if isinstance(batch, list):
                records.extend(batch)
            elif isinstance(batch, dict):
                records.extend(batch.get("records", []) or [])
    else:
        result = await sf_client.soql(soql)
        records.extend(result.get("records", []) or [])
    for record in records:
        record.pop("attributes", None)
    return records


def _normalize_metric(value: int, max_value: int) -> float:
    if max_value <= 0:
        return 0.0
    return float(value) / float(max_value)


def _score_market(
    customer_count: int,
    prospect_count: int,
    overlap_count: int,
    max_customer: int,
    max_prospect: int,
    max_overlap: int,
    weight_customer: float,
    weight_prospect: float,
    weight_overlap: float,
) -> float:
    return (
        _normalize_metric(customer_count, max_customer) * weight_customer
        + _normalize_metric(prospect_count, max_prospect) * weight_prospect
        + _normalize_metric(overlap_count, max_overlap) * weight_overlap
    )


async def build_market_finder(
    *,
    spreadsheet_id: Optional[str],
    inputs: Any,
    sheets_service,
    sf_client,
    title: str = "Field Marketing Market Finder",
) -> Dict[str, Any]:
    """
    Build the market finder workbook.
    """
    payload = _inputs_to_dict(inputs)
    _validate_market_finder_inputs(payload)

    customer_filter_field = str(payload.get("customer_filter_field") or "").strip()
    customer_filter_values = _normalize_values(payload.get("customer_filter_values"))
    customer_filter_field_type = payload.get("customer_filter_field_type") or "picklist"

    prospect_filter_field = str(payload.get("prospect_filter_field") or "").strip()
    prospect_filter_values = _normalize_values(payload.get("prospect_filter_values"))
    prospect_filter_field_type = payload.get("prospect_filter_field_type") or "picklist"
    prospect_exclude_customers = bool(payload.get("prospect_exclude_customers", True))

    geo_key_type = payload.get("geo_key_type") or "city_state"
    city_field = payload.get("city_field") or "BillingCity"
    state_field = payload.get("state_field") or "BillingState"
    zip_field = payload.get("zip_field") or "BillingPostalCode"
    country_field = payload.get("country_field") or "BillingCountry"

    weight_customer = float(payload.get("weight_customer", 0.40))
    weight_prospect = float(payload.get("weight_prospect", 0.40))
    weight_overlap = float(payload.get("weight_overlap", 0.20))

    arr_field = payload.get("arr_field")
    pipeline_field = payload.get("pipeline_field")
    contact_email_field = payload.get("contact_email_field") or "Email"
    contact_phone_field = payload.get("contact_phone_field") or "Phone"
    contact_title_field = payload.get("contact_title_field") or "Title"
    max_contacts_per_market = int(payload.get("max_contacts_per_market", 10))
    win_rate_pct = float(payload.get("win_rate_pct", 25))
    event_cost_per_attendee = float(payload.get("event_cost_per_attendee", 150))
    event_expected_attendance = int(payload.get("event_expected_attendance", 30))
    event_meeting_conversion = float(payload.get("event_meeting_conversion", 0.40))
    event_opportunity_conversion = float(payload.get("event_opportunity_conversion", 0.25))
    if win_rate_pct <= 1:
        win_rate_pct *= 100
    if event_meeting_conversion > 1:
        event_meeting_conversion /= 100
    if event_opportunity_conversion > 1:
        event_opportunity_conversion /= 100

    top_n_markets = int(payload.get("top_n_markets", 25))
    min_accounts = int(payload.get("min_accounts", 3))
    enable_drilldown = bool(payload.get("enable_drilldown", True))

    suffix = payload.get("tab_suffix") or ""
    replace_existing = (payload.get("idempotency_action") or "") == "replace"

    ranking_tab = f"Market_Ranking{suffix}"
    breakdown_tab = f"Market_Breakdown{suffix}"
    customers_tab = f"Customers_Drilldown{suffix}"
    prospects_tab = f"Prospects_Drilldown{suffix}"
    overlap_tab = f"Overlap_Drilldown{suffix}"
    invite_tab = f"Invite_List{suffix}"
    events_tab = f"Event_Recommendations{suffix}"

    created = False
    if spreadsheet_id is None:
        spreadsheet = sheets_service.spreadsheets().create(
            body={"properties": {"title": title}}
        ).execute()
        spreadsheet_id = spreadsheet["spreadsheetId"]
        created = True

    _ensure_sheets(
        sheets_service,
        spreadsheet_id,
        [
            ranking_tab,
            breakdown_tab,
            customers_tab,
            prospects_tab,
            overlap_tab,
            invite_tab,
            events_tab,
        ],
        replace=replace_existing,
    )

    select_fields: List[str] = [
        "Id",
        "Name",
        str(city_field),
        str(state_field),
        str(zip_field),
        str(country_field),
    ]
    if arr_field:
        select_fields.append(str(arr_field))
    if pipeline_field:
        select_fields.append(str(pipeline_field))
    select_fields = list(dict.fromkeys([f for f in select_fields if f]))

    customer_clause = _build_filter_clause(
        customer_filter_field, customer_filter_values, customer_filter_field_type
    )
    customer_soql = f"SELECT {', '.join(select_fields)} FROM Account WHERE {customer_clause}"

    customers = await _fetch_records(sf_client, customer_soql)
    prospect_records: List[Dict[str, Any]] = []
    if prospect_filter_field:
        prospect_clause = _build_filter_clause(
            prospect_filter_field, prospect_filter_values, prospect_filter_field_type
        )
        prospect_soql = f"SELECT {', '.join(select_fields)} FROM Account WHERE {prospect_clause}"
        prospect_records = await _fetch_records(sf_client, prospect_soql)

    market_stats: Dict[str, Dict[str, Any]] = defaultdict(
        lambda: {
            "customer_ids": set(),
            "prospect_ids_raw": set(),
            "customer_arr_by_id": {},
            "prospect_pipeline_by_id": {},
        }
    )
    customer_records_by_id: Dict[str, Dict[str, Any]] = {}
    prospect_records_by_id: Dict[str, Dict[str, Any]] = {}

    for record in customers:
        account_id = record.get("Id")
        if not account_id:
            continue
        market = _normalize_geo_key(
            geo_key_type,
            record.get(city_field),
            record.get(state_field),
            record.get(zip_field),
            record.get(country_field),
        )
        stats = market_stats[market]
        stats["customer_ids"].add(account_id)
        if arr_field:
            stats["customer_arr_by_id"][account_id] = _safe_float(record.get(arr_field))
        customer_records_by_id[account_id] = record

    for record in prospect_records:
        account_id = record.get("Id")
        if not account_id:
            continue
        market = _normalize_geo_key(
            geo_key_type,
            record.get(city_field),
            record.get(state_field),
            record.get(zip_field),
            record.get(country_field),
        )
        stats = market_stats[market]
        stats["prospect_ids_raw"].add(account_id)
        if pipeline_field:
            stats["prospect_pipeline_by_id"][account_id] = _safe_float(
                record.get(pipeline_field)
            )
        prospect_records_by_id[account_id] = record

    market_rows: List[Dict[str, Any]] = []
    eligible_stats: Dict[str, Dict[str, Any]] = {}
    for market, stats in market_stats.items():
        customer_ids = stats["customer_ids"]
        prospect_ids_raw = stats["prospect_ids_raw"]
        overlap_ids = customer_ids & prospect_ids_raw
        prospect_ids = (
            prospect_ids_raw - customer_ids if prospect_exclude_customers else prospect_ids_raw
        )
        total_ids = customer_ids | prospect_ids
        customer_arr = sum(stats["customer_arr_by_id"].values()) if arr_field else 0.0
        prospect_pipeline = (
            sum(
                stats["prospect_pipeline_by_id"].get(pid, 0.0) for pid in prospect_ids
            )
            if pipeline_field
            else 0.0
        )

        record = {
            "market": market,
            "customer_count": len(customer_ids),
            "prospect_count": len(prospect_ids),
            "overlap_count": len(overlap_ids),
            "customer_arr": customer_arr,
            "prospect_pipeline": prospect_pipeline,
            "total_accounts": len(total_ids),
        }
        market_rows.append(record)
        if record["total_accounts"] >= min_accounts and not (
            min_accounts > 1 and market == UNKNOWN_MARKET
        ):
            eligible_stats[market] = record

    max_customer = max([r["customer_count"] for r in eligible_stats.values()] or [0])
    max_prospect = max([r["prospect_count"] for r in eligible_stats.values()] or [0])
    max_overlap = max([r["overlap_count"] for r in eligible_stats.values()] or [0])

    scored_rows = []
    for record in eligible_stats.values():
        score = _score_market(
            record["customer_count"],
            record["prospect_count"],
            record["overlap_count"],
            max_customer,
            max_prospect,
            max_overlap,
            weight_customer,
            weight_prospect,
            weight_overlap,
        )
        record["score"] = score
        scored_rows.append(record)

    scored_rows.sort(key=lambda r: (r["score"], r["market"]), reverse=True)
    top_rows = scored_rows[: max(top_n_markets, 1)]

    ranking_rows = [
        [
            "Rank",
            "Market",
            "Customers",
            "Prospects",
            "Overlap Accounts",
            "Customer ARR",
            "Prospect Pipeline",
            "Score",
        ]
    ]
    # Calculate row range for VLOOKUP into Market_Breakdown
    # Market_Breakdown has: row 1-2 parameters, row 3 headers, row 4+ data
    breakdown_data_start = 4
    breakdown_last_row = 3 + len(top_rows)

    for idx, record in enumerate(top_rows, start=1):
        current_row = idx + 1  # Data starts at row 2 in Market_Ranking
        # Use VLOOKUP to get all metrics from Market_Breakdown (single source of truth)
        # VLOOKUP(market_name, breakdown_range, column_index, exact_match)
        # Columns in Breakdown: A=Market, B=Customers, C=Prospects, D=Overlap, E=Total, F-I=derived
        customers_formula = (
            f"=VLOOKUP(B{current_row},{_quote_tab(breakdown_tab)}!$A${breakdown_data_start}"
            f":$L${breakdown_last_row},2,FALSE)"
        )
        prospects_formula = (
            f"=VLOOKUP(B{current_row},{_quote_tab(breakdown_tab)}!$A${breakdown_data_start}"
            f":$L${breakdown_last_row},3,FALSE)"
        )
        overlap_formula = (
            f"=VLOOKUP(B{current_row},{_quote_tab(breakdown_tab)}!$A${breakdown_data_start}"
            f":$L${breakdown_last_row},4,FALSE)"
        )
        score_formula = (
            f"=VLOOKUP(B{current_row},{_quote_tab(breakdown_tab)}!$A${breakdown_data_start}"
            f":$L${breakdown_last_row},9,FALSE)"
        )
        ranking_rows.append(
            [
                idx,
                record["market"],
                customers_formula,
                prospects_formula,
                overlap_formula,
                record["customer_arr"] if arr_field else "",
                record["prospect_pipeline"] if pipeline_field else "",
                score_formula,
            ]
        )

    total_customers = sum(r["customer_count"] for r in eligible_stats.values())
    total_prospects = sum(r["prospect_count"] for r in eligible_stats.values())
    total_overlap = sum(r["overlap_count"] for r in eligible_stats.values())

    # Build Market_Breakdown with parameters and formulas
    # Row 1: Parameters label
    # Row 2: Weight values (user can adjust to recalculate scores)
    # Row 3: Column headers
    # Row 4+: Data with formulas
    breakdown_rows = [
        [
            "Parameters",
            "Customer Weight",
            "Prospect Weight",
            "Overlap Weight",
            "Win Rate %",
            "",
            "",
            "",
            "",
            "",
            "",
            "",
        ],
        [
            "",
            weight_customer,
            weight_prospect,
            weight_overlap,
            win_rate_pct,
            "",
            "",
            "",
            "",
            "",
            "",
            "",
        ],
        [
            "Market",
            "Customers",
            "Prospects",
            "Overlap",
            "Total Accounts",
            "Customer Share %",
            "Prospect Share %",
            "Overlap Share %",
            "Score",
            "Pipeline Value",
            "Projected Revenue",
            "ROI Score",
        ],
    ]

    # Calculate the last data row for formula ranges
    # Data starts at row 4, so last row = 3 + number of markets
    data_start_row = 4
    last_data_row = 3 + len(top_rows)

    for idx, record in enumerate(top_rows):
        current_row = data_start_row + idx
        # Build COUNTIF formulas for counts - references drilldown sheets
        # Market column is always G in drilldown sheets (Id, Name, city, state, zip, country, Market)
        customer_count_formula = (
            f"=COUNTIF({_quote_tab(customers_tab)}!$G:$G,A{current_row})"
        )
        prospect_count_formula = (
            f"=COUNTIF({_quote_tab(prospects_tab)}!$G:$G,A{current_row})"
        )
        overlap_count_formula = (
            f"=COUNTIF({_quote_tab(overlap_tab)}!$G:$G,A{current_row})"
        )
        # Total = Customers + Prospects (prospects already excludes customers when prospect_exclude_customers=True)
        total_accounts_formula = f"=B{current_row}+C{current_row}"

        # Build formulas for share percentages and score
        # Customer Share %: =IF(SUM(B$4:B$N)=0,0,B{row}/SUM(B$4:B$N)*100)
        customer_share_formula = (
            f"=IF(SUM(B${data_start_row}:B${last_data_row})=0,0,"
            f"B{current_row}/SUM(B${data_start_row}:B${last_data_row})*100)"
        )
        prospect_share_formula = (
            f"=IF(SUM(C${data_start_row}:C${last_data_row})=0,0,"
            f"C{current_row}/SUM(C${data_start_row}:C${last_data_row})*100)"
        )
        overlap_share_formula = (
            f"=IF(SUM(D${data_start_row}:D${last_data_row})=0,0,"
            f"D{current_row}/SUM(D${data_start_row}:D${last_data_row})*100)"
        )
        # Score formula: weighted normalized score
        # =(IFERROR(B{row}/MAX(B$4:B$N),0)*$B$2 + IFERROR(C{row}/MAX(...),0)*$C$2 + ...)*100
        score_formula = (
            f"=(IFERROR(B{current_row}/MAX(B${data_start_row}:B${last_data_row}),0)*$B$2"
            f"+IFERROR(C{current_row}/MAX(C${data_start_row}:C${last_data_row}),0)*$C$2"
            f"+IFERROR(D{current_row}/MAX(D${data_start_row}:D${last_data_row}),0)*$D$2)*100"
        )
        pipeline_value_formula = (
            f"=IFERROR(SUMIF({_quote_tab(prospects_tab)}!$G:$G,A{current_row},"
            f"{_quote_tab(prospects_tab)}!$H:$H),0)"
        )
        projected_revenue_formula = f"=IFERROR(J{current_row}*$E$2/100,0)"
        roi_score_formula = (
            f"=IF(MAX(K${data_start_row}:K${last_data_row})=0,I{current_row},"
            f"(I{current_row}*0.5)+(K{current_row}/MAX(K${data_start_row}:K${last_data_row})*50))"
        )

        breakdown_rows.append(
            [
                record["market"],
                customer_count_formula,
                prospect_count_formula,
                overlap_count_formula,
                total_accounts_formula,
                customer_share_formula,
                prospect_share_formula,
                overlap_share_formula,
                score_formula,
                pipeline_value_formula,
                projected_revenue_formula,
                roi_score_formula,
            ]
        )

    customers_rows = [
        [
            "Id",
            "Name",
            str(city_field),
            str(state_field),
            str(zip_field),
            str(country_field),
            "Market",
        ]
    ]
    if arr_field:
        customers_rows[0].append(str(arr_field))

    for record in customers:
        market = _normalize_geo_key(
            geo_key_type,
            record.get(city_field),
            record.get(state_field),
            record.get(zip_field),
            record.get(country_field),
        )
        row = [
            record.get("Id", ""),
            record.get("Name", ""),
            record.get(city_field, ""),
            record.get(state_field, ""),
            record.get(zip_field, ""),
            record.get(country_field, ""),
            market,
        ]
        if arr_field:
            row.append(record.get(arr_field, ""))
        customers_rows.append(row)

    prospects_rows = [
        [
            "Id",
            "Name",
            str(city_field),
            str(state_field),
            str(zip_field),
            str(country_field),
            "Market",
        ]
    ]
    if pipeline_field:
        prospects_rows[0].append(str(pipeline_field))

    for record in prospect_records:
        if prospect_exclude_customers and record.get("Id") in customer_records_by_id:
            continue
        market = _normalize_geo_key(
            geo_key_type,
            record.get(city_field),
            record.get(state_field),
            record.get(zip_field),
            record.get(country_field),
        )
        row = [
            record.get("Id", ""),
            record.get("Name", ""),
            record.get(city_field, ""),
            record.get(state_field, ""),
            record.get(zip_field, ""),
            record.get(country_field, ""),
            market,
        ]
        if pipeline_field:
            row.append(record.get(pipeline_field, ""))
        prospects_rows.append(row)

    overlap_rows = [
        [
            "Id",
            "Name",
            str(city_field),
            str(state_field),
            str(zip_field),
            str(country_field),
            "Market",
        ]
    ]
    if arr_field:
        overlap_rows[0].append(str(arr_field))
    if pipeline_field:
        overlap_rows[0].append(str(pipeline_field))

    overlap_ids = set(customer_records_by_id.keys()) & set(prospect_records_by_id.keys())
    for account_id in overlap_ids:
        record = dict(prospect_records_by_id.get(account_id) or {})
        record.update(customer_records_by_id.get(account_id) or {})
        market = _normalize_geo_key(
            geo_key_type,
            record.get(city_field),
            record.get(state_field),
            record.get(zip_field),
            record.get(country_field),
        )
        row = [
            record.get("Id", ""),
            record.get("Name", ""),
            record.get(city_field, ""),
            record.get(state_field, ""),
            record.get(zip_field, ""),
            record.get(country_field, ""),
            market,
        ]
        if arr_field:
            row.append(record.get(arr_field, ""))
        if pipeline_field:
            row.append(record.get(pipeline_field, ""))
        overlap_rows.append(row)

    invite_rows = [
        [
            "Market",
            "Account Name",
            "Account ARR",
            "Contact Name",
            "Title",
            "Email",
            "Phone",
            "Invite Priority",
        ]
    ]
    invite_accounts: Dict[str, Dict[str, Any]] = {}

    def _register_invite_account(record: Dict[str, Any], is_customer: bool, is_prospect: bool) -> None:
        account_id = record.get("Id")
        if not account_id:
            return
        market = _normalize_geo_key(
            geo_key_type,
            record.get(city_field),
            record.get(state_field),
            record.get(zip_field),
            record.get(country_field),
        )
        existing = invite_accounts.get(account_id)
        if existing:
            existing["is_customer"] = existing["is_customer"] or is_customer
            existing["is_prospect"] = existing["is_prospect"] or is_prospect
            return
        invite_accounts[account_id] = {
            "record": record,
            "market": market,
            "is_customer": is_customer,
            "is_prospect": is_prospect,
        }

    for record in customers:
        _register_invite_account(record, True, False)
    for record in prospect_records:
        if prospect_exclude_customers and record.get("Id") in customer_records_by_id:
            continue
        _register_invite_account(record, False, True)

    top_markets = [row["market"] for row in top_rows]
    top_market_set = set(top_markets)
    invite_account_ids = [
        account_id
        for account_id, entry in invite_accounts.items()
        if entry["market"] in top_market_set
    ]

    contact_records: List[Dict[str, Any]] = []
    if invite_account_ids:
        contact_fields = ["Id", "FirstName", "LastName", "AccountId"]
        for field in [contact_email_field, contact_phone_field, contact_title_field]:
            field = str(field or "").strip()
            if field and field not in contact_fields:
                contact_fields.append(field)

        def _chunked(values: List[str], size: int) -> List[List[str]]:
            return [values[i : i + size] for i in range(0, len(values), size)]

        email_filter = ""
        if contact_email_field:
            email_filter = f" AND {contact_email_field} != null"

        for chunk in _chunked(invite_account_ids, 200):
            in_clause = ",".join(f"'{_escape_soql_literal(v)}'" for v in chunk)
            contact_soql = (
                f"SELECT {', '.join(contact_fields)} FROM Contact"
                f" WHERE AccountId IN ({in_clause}){email_filter}"
                " ORDER BY CreatedDate DESC"
            )
            contact_records.extend(await _fetch_records(sf_client, contact_soql))

    contacts_by_account: Dict[str, List[Dict[str, Any]]] = defaultdict(list)
    for contact in contact_records:
        account_id = contact.get("AccountId")
        if not account_id:
            continue
        contacts_by_account[account_id].append(contact)

    accounts_by_market: Dict[str, List[Dict[str, Any]]] = defaultdict(list)
    for entry in invite_accounts.values():
        if entry["market"] in top_market_set:
            accounts_by_market[entry["market"]].append(entry)

    max_contacts_per_account = 2
    for market in top_markets:
        account_entries = accounts_by_market.get(market, [])
        account_entries.sort(
            key=lambda e: _safe_float(e["record"].get(arr_field)) if arr_field else 0.0,
            reverse=True,
        )
        account_entries = account_entries[: max(max_contacts_per_market, 1)]
        for entry in account_entries:
            record = entry["record"]
            account_id = record.get("Id")
            account_contacts = contacts_by_account.get(account_id, [])
            if not account_contacts:
                row_num = len(invite_rows) + 1
                if arr_field:
                    priority_formula = (
                        f"=IF(COUNTIF({_quote_tab(customers_tab)}!$B:$B,B{row_num})>0,"
                        f"IFERROR(IF(C{row_num}>=PERCENTILE($C:$C,0.75),\"High\",\"Medium\"),\"High\"),"
                        f"IFERROR(IF(C{row_num}>=PERCENTILE($C:$C,0.75),\"Medium\",\"Low\"),\"Medium\"))"
                    )
                else:
                    priority_formula = (
                        f"=IF(COUNTIF({_quote_tab(customers_tab)}!$B:$B,B{row_num})>0,\"High\",\"Medium\")"
                    )
                invite_rows.append(
                    [
                        entry["market"],
                        record.get("Name", ""),
                        record.get(arr_field, "") if arr_field else "",
                        "",
                        "",
                        "",
                        "",
                        priority_formula,
                    ]
                )
                continue
            for contact in account_contacts[:max_contacts_per_account]:
                row_num = len(invite_rows) + 1
                if arr_field:
                    priority_formula = (
                        f"=IF(COUNTIF({_quote_tab(customers_tab)}!$B:$B,B{row_num})>0,"
                        f"IFERROR(IF(C{row_num}>=PERCENTILE($C:$C,0.75),\"High\",\"Medium\"),\"High\"),"
                        f"IFERROR(IF(C{row_num}>=PERCENTILE($C:$C,0.75),\"Medium\",\"Low\"),\"Medium\"))"
                    )
                else:
                    priority_formula = (
                        f"=IF(COUNTIF({_quote_tab(customers_tab)}!$B:$B,B{row_num})>0,\"High\",\"Medium\")"
                    )
                contact_name = " ".join(
                    [str(contact.get("FirstName") or "").strip(), str(contact.get("LastName") or "").strip()]
                ).strip()
                invite_rows.append(
                    [
                        entry["market"],
                        record.get("Name", ""),
                        record.get(arr_field, "") if arr_field else "",
                        contact_name,
                        contact.get(contact_title_field, ""),
                        contact.get(contact_email_field, ""),
                        contact.get(contact_phone_field, ""),
                        priority_formula,
                    ]
                )

    if len(invite_rows) == 1:
        invite_rows.append(["No invite data available."])

    event_rows = [
        ["Event Assumptions", "", ""],
        ["Cost per Attendee", event_cost_per_attendee, ""],
        ["Expected Attendance", event_expected_attendance, "accounts per event"],
        ["Meeting Conversion", event_meeting_conversion, "of attendees take meeting"],
        ["Opportunity Conversion", event_opportunity_conversion, "of meetings create opp"],
        [
            "Average Opp Size",
            f"=IFERROR(AVERAGE({_quote_tab(prospects_tab)}!$H:$H),0)",
            "",
        ],
        ["Win Rate", f"=IFERROR({_sheet_cell(breakdown_tab, '$E$2')}/100,0)", ""],
        [],
        [
            "Rank",
            "Market",
            "Prospects",
            "Est. Pipeline",
            "Est. Revenue",
            "Event Cost",
            "Projected ROI",
        ],
    ]

    has_breakdown_data = last_data_row >= data_start_row
    if has_breakdown_data:
        sorted_range = (
            f"SORT({_quote_tab(breakdown_tab)}!$A${data_start_row}:$L${last_data_row},12,FALSE)"
        )
    for rank in range(1, 4):
        # Append placeholder first so row_num reflects the final row position in the sheet.
        event_rows.append([rank, "", "", "", "", "", ""])
        row_num = len(event_rows)
        if has_breakdown_data:
            market_formula = f"=IFERROR(INDEX({sorted_range},{rank},1),\"\")"
            prospects_formula = f"=IFERROR(INDEX({sorted_range},{rank},3),0)"
        else:
            market_formula = ""
            prospects_formula = 0
        est_pipeline_formula = f"=IFERROR(MIN(C{row_num},$B$3)*$B$4*$B$5*$B$6,0)"
        est_revenue_formula = f"=IFERROR(D{row_num}*$B$7,0)"
        event_cost_formula = f"=IFERROR(MIN(C{row_num},$B$3)*$B$2,0)"
        roi_formula = f"=IFERROR((E{row_num}-F{row_num})/F{row_num}*100,0)"
        event_rows[-1] = [
            rank,
            market_formula,
            prospects_formula,
            est_pipeline_formula,
            est_revenue_formula,
            event_cost_formula,
            roi_formula,
        ]

    _write_rows(sheets_service, spreadsheet_id, ranking_tab, ranking_rows)
    _write_rows(sheets_service, spreadsheet_id, breakdown_tab, breakdown_rows)

    if enable_drilldown:
        _write_rows(sheets_service, spreadsheet_id, customers_tab, customers_rows)
        _write_rows(sheets_service, spreadsheet_id, prospects_tab, prospects_rows)
        _write_rows(sheets_service, spreadsheet_id, overlap_tab, overlap_rows)
    else:
        _write_rows(
            sheets_service,
            spreadsheet_id,
            customers_tab,
            [["Drilldown disabled. Enable drilldown to view customer records."]],
        )
        _write_rows(
            sheets_service,
            spreadsheet_id,
            prospects_tab,
            [["Drilldown disabled. Enable drilldown to view prospect records."]],
        )
        _write_rows(
            sheets_service,
            spreadsheet_id,
            overlap_tab,
            [["Drilldown disabled. Enable drilldown to view overlap records."]],
        )

    _write_rows(sheets_service, spreadsheet_id, invite_tab, invite_rows)
    _write_rows(sheets_service, spreadsheet_id, events_tab, event_rows)

    validation_errors: List[str] = []
    if not customers and not prospect_records:
        validation_errors.append("No accounts returned for the selected filters.")
    if not eligible_stats:
        validation_errors.append("No markets met the minimum account threshold.")

    validation = {
        "status": "issues" if validation_errors else "ok",
        "errors": validation_errors,
    }

    summary = {
        "markets_analyzed": len(market_stats),
        "markets_ranked": len(eligible_stats),
        "total_customers": len(customers),
        "total_prospects": len(prospect_records),
        "total_overlap": len(overlap_ids),
        "top_markets": len(top_rows),
    }

    return {
        "spreadsheet_id": spreadsheet_id,
        "url": f"https://docs.google.com/spreadsheets/d/{spreadsheet_id}",
        "tabs_created": [
            ranking_tab,
            breakdown_tab,
            customers_tab,
            prospects_tab,
            overlap_tab,
            invite_tab,
            events_tab,
        ],
        "created": created,
        "validation": validation,
        "summary": summary,
    }
