"""
Lightweight tool registry for Gremlin mode routing.

This registry is separate from gremlin_tools.py (execution metadata) and is
used to shape prompts and tool allowlists per mode.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import List, Set

from .gremlin_intent_router import GremlinMode


@dataclass
class ToolConstraints:
    max_cells_per_action: int = 500
    max_rows_per_batch: int = 100
    allow_web_search: bool = False
    allow_external_api: bool = True
    require_preview: bool = True  # Must show plan before executing


@dataclass
class ToolDefinition:
    name: str
    description: str
    parameters: dict
    modes: Set[GremlinMode]
    is_read_only: bool = False
    is_write: bool = False


@dataclass
class ToolSet:
    tools: List[ToolDefinition]
    constraints: ToolConstraints

    def get_tool_names(self) -> List[str]:
        return [tool.name for tool in self.tools]


UNIVERSAL_TOOLS: List[ToolDefinition] = [
    ToolDefinition(
        name="READ_SHEET",
        description="Read headers + sample rows from another sheet tab",
        parameters={"sheet_name": "tab name"},
        modes={GremlinMode.DATA_QUALITY, GremlinMode.MODEL, GremlinMode.RESEARCH},
        is_read_only=True,
    ),
]


def _make_tool(
    name: str,
    description: str,
    parameters: dict,
    modes: Set[GremlinMode],
    read_only: bool = False,
    write: bool = True,
) -> ToolDefinition:
    """Helper to build ToolDefinition entries."""
    return ToolDefinition(
        name=name,
        description=description,
        parameters=parameters,
        modes=modes,
        is_read_only=read_only,
        is_write=write,
    )


# NOTE: SFDC write tools (e.g., sfdc_push_campaign) are intentionally excluded
# from Gremlin Chat toolsets. Salesforce writeback operations should only be
# accessible through the dedicated "Salesforce" menu UI with explicit user
# confirmation. This ensures Gremlin remains a sheet-local AI assistant without
# accidental external system writes.
DQ_TRANSFORM_METADATA = [
    {"name": "assign_global_region", "description": "Assign global sales regions from country values.", "parameters": {"range": "country column"}},
    {"name": "assign_territory", "description": "Assign sales territories using geography and firmographics.", "parameters": {"range": "rows with geo/firmographic columns"}},
    {"name": "assign_us_region", "description": "Group US states into sales regions.", "parameters": {"range": "US state column"}},
    {"name": "calculate_completeness", "description": "Score how complete each row is and list missing fields.", "parameters": {"range": "rows to score"}},
    {"name": "calculate_lead_score", "description": "Calculate lead scores from firmographic and behavioral signals.", "parameters": {"range": "rows to score"}},
    {"name": "classify_lead_source", "description": "Classify lead source using UTM or referrer context.", "parameters": {"range": "lead source text or URLs", "utm": "optional UTM object", "referrer": "optional referrer URL"}},
    {"name": "classify_revenue_band", "description": "Classify revenues into standard bands.", "parameters": {"range": "revenue column"}},
    {"name": "clean_name", "description": "Normalize personal names with proper casing.", "parameters": {"range": "name column"}},
    {"name": "clean_website", "description": "Normalize websites to canonical https URLs.", "parameters": {"range": "website or URL column"}},
    {"name": "company_size_bucket", "description": "Bucket company sizes into standard employee segments.", "parameters": {"range": "employee counts or size column"}},
    {"name": "company_to_domain", "description": "Resolve company names to domains with confidence scores.", "parameters": {"range": "company column", "mode": "optional resolution mode", "auto_link_threshold": "optional auto-link confidence", "suggest_threshold": "optional suggestion threshold"}},
    {"name": "detect_data_quality_issues", "description": "Flag likely data quality issues with reasons.", "parameters": {"range": "rows to scan"}},
    {"name": "detect_duplicate_likelihood", "description": "Estimate duplicate likelihood per row.", "parameters": {"range": "rows to score", "mode": "optional blocking mode", "threshold": "optional threshold 0-1"}},
    {"name": "detect_parent_company", "description": "Detect likely parent companies for each account.", "parameters": {"range": "rows with company and domain"}},
    {"name": "detect_technographics", "description": "Detect CRM, marketing platform, and hosting provider signals.", "parameters": {"range": "rows with domains/descriptions"}},
    {"name": "email_domain_match", "description": "Check if email domains align with company domains.", "parameters": {"range": "two-column range: email then company/domain"}},
    {"name": "enrich_company_country", "description": "Enrich company country from profiles.", "parameters": {"range": "company domain or name"}},
    {"name": "enrich_company_headquarters", "description": "Enrich company headquarters locations.", "parameters": {"range": "company domain or name"}},
    {"name": "enrich_company_industry", "description": "Enrich company industry fields.", "parameters": {"range": "company domain or name"}},
    {"name": "enrich_company_name", "description": "Resolve canonical company names from domain/website.", "parameters": {"range": "company domain or name"}},
    {"name": "enrich_company_revenue", "description": "Enrich company revenue (amount, currency, year).", "parameters": {"range": "company domain or name"}},
    {"name": "enrich_from_foundrygraph", "description": "Enrich company data with all available FoundryGraph fields.", "parameters": {"range": "company domain or name", "input_type": "domain or company_name"}},
    {"name": "enrich_social_handles", "description": "Enrich company social handles.", "parameters": {"range": "company domain or name"}},
    {"name": "enrich_stock_info", "description": "Enrich stock ticker and exchange info.", "parameters": {"range": "company domain or name"}},
    {"name": "enrich_subsidiaries", "description": "Enrich companies with subsidiary counts and names.", "parameters": {"range": "company domain or name"}},
    {"name": "extract_domain_from_email", "description": "Extract domains from email addresses.", "parameters": {"range": "email column", "strip_b2c": "optional personal-domain filter"}},
    {"name": "extract_domain_root", "description": "Extract the registrable root domain from URLs or emails.", "parameters": {"range": "URL, domain, or email column"}},
    {"name": "extract_id_from_url", "description": "Parse provider, record type, and identifier from URLs.", "parameters": {"range": "URL column"}},
    {"name": "extract_subdomain", "description": "Extract the subdomain portion from URLs or domains.", "parameters": {"range": "URL or domain column"}},
    {"name": "fix_phone_format", "description": "Format phone numbers to international E.164.", "parameters": {"range": "phone column", "country": "optional country"}},
    {"name": "generate_dedup_key", "description": "Generate composite deduplication keys per row.", "parameters": {"range": "rows to build dedup keys"}},
    {"name": "infer_employee_count", "description": "Predict employee count ranges with confidence.", "parameters": {"range": "rows or company column"}},
    {"name": "is_business_email", "description": "Flag business vs personal email addresses.", "parameters": {"range": "email column"}},
    {"name": "is_role_based_email", "description": "Detect role-based or generic inboxes.", "parameters": {"range": "email column"}},
    {"name": "normalize_company", "description": "Standardize company names.", "parameters": {"range": "company column", "force_llm": "optional force flag"}},
    {"name": "normalize_country", "description": "Normalize country names to canonical values.", "parameters": {"range": "country column"}},
    {"name": "normalize_industry", "description": "Normalize industry names to standard categories.", "parameters": {"range": "industry column", "force_llm": "optional force flag"}},
    {"name": "normalize_job_function", "description": "Normalize job titles into functional departments.", "parameters": {"range": "job title column", "force_llm": "optional force flag"}},
    {"name": "normalize_phone_to_e164", "description": "Normalize phone numbers to E.164 format.", "parameters": {"range": "phone column", "country": "optional country"}},
    {"name": "normalize_state", "description": "Standardize state or province values.", "parameters": {"range": "state/province column", "country": "optional country"}},
    {"name": "normalize_title", "description": "Standardize job titles into title/department/seniority.", "parameters": {"range": "title column"}},
    {"name": "parse_address_components", "description": "Split addresses into street, city, state, and postal code.", "parameters": {"range": "address column"}},
    {"name": "parse_email_pattern", "description": "Detect the naming convention for email addresses.", "parameters": {"range": "email column"}},
    {"name": "parse_naics", "description": "Map NAICS text to standardized codes.", "parameters": {"range": "NAICS description column"}},
    {"name": "parse_sic", "description": "Map SIC text to standardized codes.", "parameters": {"range": "SIC description column"}},
    {"name": "split_fullname", "description": "Split full names into first and last name columns.", "parameters": {"range": "full name column"}},
    {"name": "state_name_to_code", "description": "Convert state or province names to two-letter codes.", "parameters": {"range": "state/province column"}},
]

TRANSFORM_METADATA = {meta["name"]: meta for meta in DQ_TRANSFORM_METADATA}

DATA_QUALITY_TOOLS: List[ToolDefinition] = [
    ToolDefinition(
        name="UPDATE_CELLS",
        description="Update specific cells with new values. Surgical fixes.",
        parameters={"updates": "[{range: 'A2', value: 'Fixed Value'}, ...]"},
        modes={GremlinMode.DATA_QUALITY},
        is_write=True,
    ),
    ToolDefinition(
        name="dedupe",
        description="Find and resolve duplicate rows based on specified columns.",
        parameters={"key_columns": "columns to compare", "threshold": "similarity threshold 0-1"},
        modes={GremlinMode.DATA_QUALITY},
        is_write=True,
    ),
    ToolDefinition(
        name="resolve_company",
        description="Resolve company names using Salesforce or FoundryGraph. Default smart waterfall.",
        parameters={
            "range": "column with company names",
            "target": "salesforce | foundrygraph | smart",
        },
        modes={GremlinMode.DATA_QUALITY, GremlinMode.RESEARCH},
        is_write=True,
    ),
    ToolDefinition(
        name="match_salesforce_account",
        description="Match companies against Salesforce Accounts; returns Account ID and name.",
        parameters={
            "range": "column with company names",
            "threshold": "match threshold 0-100 (default 80)",
        },
        modes={GremlinMode.DATA_QUALITY},
        is_write=True,
    ),
] + [
    _make_tool(
        meta["name"],
        meta["description"],
        meta["parameters"],
        {GremlinMode.DATA_QUALITY},
    )
    for meta in DQ_TRANSFORM_METADATA
]

MODEL_TOOLS: List[ToolDefinition] = [
    ToolDefinition(
        name="ADD_COLUMN",
        description="Add a new column with optional values.",
        parameters={"header": "column header", "position": "after which column"},
        modes={GremlinMode.MODEL},
        is_write=True,
    ),
    ToolDefinition(
        name="UPDATE_CELLS",
        description="Write formulas or values to a target range.",
        parameters={"range": "target range", "values": "2D array or formulas"},
        modes={GremlinMode.MODEL},
        is_write=True,
    ),
    ToolDefinition(
        name="STYLE_RANGE",
        description="Apply formatting to a range.",
        parameters={"range": "target range", "style": "number_format | bold | color | etc"},
        modes={GremlinMode.MODEL},
        is_write=True,
    ),
]

RESEARCH_TOOLS: List[ToolDefinition] = [
    ToolDefinition(
        name="UPDATE_CELLS",
        description="Write enrichment results back to the sheet.",
        parameters={"updates": "[{range: 'G2', value: 'Industry'}, ...]"},
        modes={GremlinMode.RESEARCH},
        is_write=True,
    ),
    ToolDefinition(
        name="resolve_company",
        description="Resolve company names using Salesforce or FoundryGraph. Default smart waterfall.",
        parameters={
            "range": "column with company names",
            "target": "salesforce | foundrygraph | smart",
        },
        modes={GremlinMode.RESEARCH},
        is_write=True,
    ),
] + [
    _make_tool(
        TRANSFORM_METADATA[name]["name"],
        TRANSFORM_METADATA[name]["description"],
        TRANSFORM_METADATA[name]["parameters"],
        {GremlinMode.RESEARCH},
    )
    for name in [
        "company_to_domain",
        "detect_parent_company",
        "enrich_company_name",
        "enrich_company_industry",
        "enrich_company_country",
        "enrich_company_headquarters",
        "enrich_company_revenue",
        "enrich_from_foundrygraph",
        "enrich_social_handles",
        "enrich_stock_info",
        "enrich_subsidiaries",
        "detect_technographics",
        "infer_employee_count",
        "assign_global_region",
        "assign_territory",
    ]
]

MODE_TOOL_SETS = {
    GremlinMode.DATA_QUALITY: ToolSet(
        tools=UNIVERSAL_TOOLS + DATA_QUALITY_TOOLS,
        constraints=ToolConstraints(
            max_cells_per_action=500,
            max_rows_per_batch=100,
            allow_web_search=False,
            require_preview=True,
        ),
    ),
    GremlinMode.MODEL: ToolSet(
        tools=UNIVERSAL_TOOLS + MODEL_TOOLS,
        constraints=ToolConstraints(
            max_cells_per_action=0,  # Not applicable for formulas
            max_rows_per_batch=100,
            allow_web_search=False,
            require_preview=True,
        ),
    ),
    GremlinMode.RESEARCH: ToolSet(
        tools=UNIVERSAL_TOOLS + RESEARCH_TOOLS,
        constraints=ToolConstraints(
            max_cells_per_action=1000,
            max_rows_per_batch=50,
            allow_web_search=True,
            allow_external_api=True,
            require_preview=True,
        ),
    ),
}


def get_tools_for_mode(mode: GremlinMode) -> ToolSet:
    return MODE_TOOL_SETS[mode]
