"""
Artefact Revenue Intelligence MCP Server

FastMCP server that exposes 3 revenue intelligence tools and 4 methodology resources.
Free tier works with sample data. Pro/Enterprise tiers require ARTEFACT_LICENSE_KEY.
"""

import json
import os
import sys
from typing import Optional

from fastmcp import FastMCP

from artefact_mcp.core.hubspot_client import HubSpotClient
from artefact_mcp.core.license import validate_license, require_license, LicenseInfo
from artefact_mcp.core.property_mappings import PropertyMapping, DEFAULT_PROPERTY_MAPPING
from artefact_mcp.core.rfm_thresholds import RFMThresholds
from artefact_mcp.core.config_validator import (
    load_json_safely,
    validate_property_mapping_config,
    validate_rfm_thresholds_config,
    sanitize_error_message,
)
from artefact_mcp.tools.rfm import run_rfm_analysis
from artefact_mcp.tools.icp import qualify_prospect
from artefact_mcp.tools.pipeline import score_pipeline
from artefact_mcp.resources.methodology import get_resource, list_resources

# --- License validation at startup ---
_license: LicenseInfo = validate_license()

if not _license.valid:
    print(f"[Artefact MCP] License error: {_license.error}", file=sys.stderr)
    print("[Artefact MCP] Running in free mode (sample data only).", file=sys.stderr)
    _license.tier = "free"
elif _license.tier == "free":
    print("[Artefact MCP] No license key found. Running in free mode (sample data only).", file=sys.stderr)
    print("[Artefact MCP] Purchase a license at https://artefactventures.lemonsqueezy.com", file=sys.stderr)
else:
    print(f"[Artefact MCP] License valid — tier: {_license.tier}", file=sys.stderr)
    if _license.customer_name:
        print(f"[Artefact MCP] Licensed to: {_license.customer_name}", file=sys.stderr)

# --- Load property mapping configuration (Pro/Enterprise only) ---
_property_mapping: Optional[PropertyMapping] = None
_property_mapping_errors: list[str] = []

if _license.tier in ("pro", "enterprise"):
    mapping_path = os.getenv("ARTEFACT_PROPERTY_MAPPING_PATH")
    if mapping_path:
        # Load and validate configuration securely
        config, error = load_json_safely(mapping_path)
        if error:
            print(f"[Artefact MCP] Property mapping validation failed: {error}", file=sys.stderr)
            print("[Artefact MCP] Using default property mapping.", file=sys.stderr)
            _property_mapping_errors.append(error)
            _property_mapping = DEFAULT_PROPERTY_MAPPING
        else:
            # Validate configuration structure
            is_valid, errors = validate_property_mapping_config(config)
            if not is_valid:
                print(f"[Artefact MCP] Property mapping configuration errors:", file=sys.stderr)
                for err in errors:
                    print(f"  - {err}", file=sys.stderr)
                print("[Artefact MCP] Using default property mapping.", file=sys.stderr)
                _property_mapping_errors.extend(errors)
                _property_mapping = DEFAULT_PROPERTY_MAPPING
            else:
                try:
                    _property_mapping = PropertyMapping(**config)
                    print(f"[Artefact MCP] Loaded custom property mapping", file=sys.stderr)
                except Exception as e:
                    safe_error = sanitize_error_message(e)
                    print(f"[Artefact MCP] Failed to create property mapping: {safe_error}", file=sys.stderr)
                    print("[Artefact MCP] Using default property mapping.", file=sys.stderr)
                    _property_mapping_errors.append(safe_error)
                    _property_mapping = DEFAULT_PROPERTY_MAPPING
    else:
        _property_mapping = DEFAULT_PROPERTY_MAPPING

# --- Load RFM threshold configuration (Pro/Enterprise only) ---
_rfm_thresholds: Optional[RFMThresholds] = None
_rfm_thresholds_errors: list[str] = []

if _license.tier in ("pro", "enterprise"):
    rfm_path = os.getenv("ARTEFACT_RFM_THRESHOLDS_PATH")
    if rfm_path:
        # Load and validate configuration securely
        config, error = load_json_safely(rfm_path)
        if error:
            print(f"[Artefact MCP] RFM thresholds validation failed: {error}", file=sys.stderr)
            print("[Artefact MCP] Using default RFM thresholds.", file=sys.stderr)
            _rfm_thresholds_errors.append(error)
        else:
            # Validate configuration structure
            is_valid, errors = validate_rfm_thresholds_config(config)
            if not is_valid:
                print(f"[Artefact MCP] RFM thresholds configuration errors:", file=sys.stderr)
                for err in errors:
                    print(f"  - {err}", file=sys.stderr)
                print("[Artefact MCP] Using default RFM thresholds.", file=sys.stderr)
                _rfm_thresholds_errors.extend(errors)
            else:
                try:
                    _rfm_thresholds = RFMThresholds(**config)
                    print(f"[Artefact MCP] Loaded custom RFM thresholds", file=sys.stderr)
                except Exception as e:
                    safe_error = sanitize_error_message(e)
                    print(f"[Artefact MCP] Failed to create RFM thresholds: {safe_error}", file=sys.stderr)
                    print("[Artefact MCP] Using default RFM thresholds.", file=sys.stderr)
                    _rfm_thresholds_errors.append(safe_error)

# --- Server ---

mcp = FastMCP(
    "Artefact Revenue Intelligence",
    instructions=(
        "Revenue intelligence tools powered by the Artefact Formula methodology. "
        "Includes RFM analysis, ICP Triangulation Framework (firmographics + behaviors + growth signals), and pipeline health scoring. "
        + (
            "Connect to HubSpot for live data or use built-in sample data. "
            "IMPORTANT: The ICP Triangulation Framework scores prospects across three dimensions. "
            "(1) Firmographic Fit: HubSpot provides industry, revenue, employees, geography. "
            "(2) Behavioral Fit: HubSpot provides tech stack, content engagement, purchase history. "
            "(3) Growth Signals (CRITICAL): Hiring, funding, expansion momentum require external enrichment via Clay, Clearbit, or manual research. "
            "Read methodology://data-requirements for complete setup instructions."
            if _license.tier != "free"
            else "Running in free mode — use source='sample' for demo data. "
            "Purchase a Pro license for live HubSpot integration."
        )
    ),
)


def _get_hubspot_client() -> Optional[HubSpotClient]:
    """Create a HubSpot client if API key is available."""
    api_key = os.getenv("HUBSPOT_API_KEY")
    if api_key:
        return HubSpotClient(api_key)
    return None


# --- Tools ---


@mcp.tool()
def run_rfm(
    source: str = "hubspot",
    industry_preset: str = "default",
) -> str:
    """Run RFM (Recency, Frequency, Monetary) analysis on client data.

    Scores clients based on purchase behavior, segments them into 11 categories,
    and extracts ICP patterns from top performers.

    Args:
        source: Data source — "hubspot" for live HubSpot data, "sample" for built-in demo data.
        industry_preset: Scoring preset — "b2b_service", "saas", "manufacturing", or "default".

    Returns:
        JSON with scored clients, segment distribution, ICP patterns, and tier recommendations.
    """
    try:
        require_license(source, _license)
    except ValueError as e:
        return json.dumps({"error": str(e)})

    client = _get_hubspot_client() if source == "hubspot" else None
    try:
        result = run_rfm_analysis(
            source=source,
            industry_preset=industry_preset,
            hubspot_client=client,
            custom_thresholds=_rfm_thresholds if _license.tier != "free" else None,
        )
        return json.dumps(result, indent=2, default=str)
    except Exception as e:
        return json.dumps({"error": str(e)})
    finally:
        if client:
            client.close()


@mcp.tool()
def qualify(
    company_id: Optional[str] = None,
    company_data: Optional[str] = None,
) -> str:
    """Score a prospect using the ICP Triangulation Framework.

    Goes beyond demographics by triangulating across three dimensions:
    - Firmographic Fit: Who they are (industry, revenue, employees, geography)
    - Behavioral Fit: What they're doing (tech stack, growth signals, engagement, purchase history)
    - Strategic Fit: Where they're heading (decision-maker access, budget authority, alignment)

    Returns tier classification (1-4), score breakdown, and recommended engagement strategy.

    Provide EITHER company_id (HubSpot ID, requires HUBSPOT_API_KEY) OR company_data (JSON string).

    Args:
        company_id: HubSpot company ID to fetch and score.
        company_data: JSON string with company attributes. Example keys:
            industry, annual_revenue, employee_count, geography, tech_stack (list),
            growth_signals (list), content_engagement ("active"|"occasional"|"none"),
            purchase_history ("regular"|"occasional"|"never"),
            decision_maker_access ("c_suite"|"director"|"manager"|"indirect"|"none"),
            budget_authority ("dedicated"|"shared"|"possible"|"none"),
            strategic_alignment ("strong"|"partial"|"misaligned").

    Returns:
        JSON with total score, tier, breakdown, exclusion check, and recommended action.
    """
    # company_id requires HubSpot = requires license
    if company_id:
        try:
            require_license("hubspot", _license)
        except ValueError as e:
            return json.dumps({"error": str(e)})

    parsed_data = None
    if company_data:
        try:
            parsed_data = json.loads(company_data) if isinstance(company_data, str) else company_data
        except (json.JSONDecodeError, TypeError) as e:
            return json.dumps({"error": f"Invalid company_data JSON: {e}"})

    client = _get_hubspot_client() if company_id else None
    try:
        result = qualify_prospect(
            company_id=company_id,
            company_data=parsed_data,
            hubspot_client=client,
            property_mapping=_property_mapping if _license.tier != "free" else None,
        )
        return json.dumps(result, indent=2, default=str)
    except Exception as e:
        return json.dumps({"error": str(e)})
    finally:
        if client:
            client.close()


@mcp.tool()
def validate_configuration() -> str:
    """Validate custom configuration files without making API calls.

    Tests property mapping and RFM threshold configurations for correctness.
    Useful for debugging configuration issues before running analysis.

    Returns:
        JSON with validation results, errors, and warnings.
    """
    results = {
        "license_tier": _license.tier,
        "property_mapping": {
            "configured": _property_mapping is not None and _property_mapping != DEFAULT_PROPERTY_MAPPING,
            "source": "custom" if _property_mapping and _property_mapping != DEFAULT_PROPERTY_MAPPING else "default",
            "errors": _property_mapping_errors,
            "status": "valid" if not _property_mapping_errors else "invalid"
        },
        "rfm_thresholds": {
            "configured": _rfm_thresholds is not None,
            "source": "custom" if _rfm_thresholds else "default",
            "errors": _rfm_thresholds_errors,
            "status": "valid" if not _rfm_thresholds_errors else "invalid"
        },
        "overall_status": "valid" if not (_property_mapping_errors or _rfm_thresholds_errors) else "invalid"
    }

    # Add configuration details if valid
    if _property_mapping and not _property_mapping_errors:
        results["property_mapping"]["details"] = {
            "tech_stack_property": _property_mapping.tech_stack,
            "growth_signals_count": len(_property_mapping.growth_signals) if _property_mapping.growth_signals else 0,
            "content_engagement_property": _property_mapping.content_engagement,
            "strategic_properties_configured": bool(
                _property_mapping.decision_maker_access or
                _property_mapping.budget_authority or
                _property_mapping.strategic_alignment
            )
        }

    if _rfm_thresholds and not _rfm_thresholds_errors:
        results["rfm_thresholds"]["details"] = {
            "recency_thresholds": _rfm_thresholds.recency_days,
            "frequency_thresholds": _rfm_thresholds.frequency_counts,
            "monetary_method": _rfm_thresholds.monetary_method
        }

    return json.dumps(results, indent=2)


@mcp.tool()
def score_pipeline_health(
    pipeline_id: Optional[str] = None,
    source: str = "hubspot",
) -> str:
    """Analyze pipeline health with velocity metrics, conversion rates, and at-risk detection.

    Calculates overall health score (0-100), identifies bottleneck stages,
    measures stage-to-stage conversion rates, and flags stalled or overdue deals.

    Args:
        pipeline_id: Optional HubSpot pipeline ID to filter. Default: all pipelines.
        source: "hubspot" for live data, "sample" for built-in demo data.

    Returns:
        JSON with health score, velocity metrics, conversion rates, at-risk deals, and stage distribution.
    """
    try:
        require_license(source, _license)
    except ValueError as e:
        return json.dumps({"error": str(e)})

    client = _get_hubspot_client() if source == "hubspot" else None
    try:
        result = score_pipeline(
            pipeline_id=pipeline_id,
            source=source,
            hubspot_client=client,
        )
        return json.dumps(result, indent=2, default=str)
    except Exception as e:
        return json.dumps({"error": str(e)})
    finally:
        if client:
            client.close()


# --- Resources ---


@mcp.resource("methodology://scoring-model")
def scoring_model() -> str:
    """ICP Triangulation Framework technical reference."""
    return get_resource("scoring-model")


@mcp.resource("methodology://tier-definitions")
def tier_definitions() -> str:
    """4-tier classification system (Ideal / Strong / Moderate / Poor)."""
    return get_resource("tier-definitions")


@mcp.resource("methodology://rfm-segments")
def rfm_segments() -> str:
    """11 RFM segment definitions with scoring scales."""
    return get_resource("rfm-segments")


@mcp.resource("methodology://spiced-framework")
def spiced_framework() -> str:
    """SPICED discovery framework reference."""
    return get_resource("spiced-framework")


@mcp.resource("methodology://data-requirements")
def data_requirements() -> str:
    """HubSpot data setup and enrichment requirements for ICP triangulation."""
    return get_resource("data-requirements")


def main():
    """Entry point for the MCP server."""
    mcp.run()


if __name__ == "__main__":
    main()
