"""
GHL MCTB Deploy Script
======================
Deploys the Missed Call Text Back (MCTB) module to a GoHighLevel sub-account
via the GHL API v2.

Usage:
    python ghl_mctb_deploy.py \
        --sub-account-id SUB_ACCOUNT_ID \
        --business-name "Precision Plumbing" \
        --booking-link "https://book.precisionplumbing.com.au" \
        --owner-phone "+61412345678"

Environment Variables:
    GHL_AGENCY_API_KEY   - GHL Agency API key (required)

GHL API Base: https://services.leadconnectorhq.com
Auth: Bearer token via Authorization header

ReceptionistAI | Lead Recovery Stack | v1.0.0
"""

import argparse
import os
import sys
import json
import time
import requests
from typing import Optional


# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------

GHL_API_BASE = "https://services.leadconnectorhq.com"
GHL_API_VERSION = "2021-07-28"


def get_agency_api_key() -> str:
    """Retrieve the GHL Agency API key from environment variables."""
    key = os.environ.get("GHL_AGENCY_API_KEY")
    if not key:
        print("[ERROR] GHL_AGENCY_API_KEY environment variable is not set.")
        print("        Export it before running: export GHL_AGENCY_API_KEY=your_key_here")
        sys.exit(1)
    return key


def build_headers(api_key: str) -> dict:
    """Build the standard GHL API v2 request headers."""
    return {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
        "Version": GHL_API_VERSION,
    }


# ---------------------------------------------------------------------------
# API Helpers
# ---------------------------------------------------------------------------

def handle_response(response: requests.Response, action: str) -> dict:
    """
    Check the API response and exit with a helpful error message if it failed.
    Returns the parsed JSON body on success.
    """
    if response.status_code in (200, 201):
        try:
            return response.json()
        except Exception:
            return {"status": "ok"}
    else:
        print(f"\n[ERROR] Failed to {action}")
        print(f"        Status: {response.status_code}")
        try:
            body = response.json()
            print(f"        Response: {json.dumps(body, indent=2)}")
        except Exception:
            print(f"        Response: {response.text}")
        sys.exit(1)


def rate_limit_pause(seconds: float = 0.5):
    """Brief pause to respect GHL rate limits."""
    time.sleep(seconds)


# ---------------------------------------------------------------------------
# Step 1: Create Custom Fields
# ---------------------------------------------------------------------------

def create_custom_field(
    sub_account_id: str,
    headers: dict,
    field_name: str,
    field_key: str,
    field_type: str = "TEXT",
    placeholder: str = "",
) -> dict:
    """
    Create a contact-level custom field in a GHL sub-account.

    GHL API: POST /contacts/custom-fields
    """
    url = f"{GHL_API_BASE}/contacts/custom-fields"
    payload = {
        "locationId": sub_account_id,
        "name": field_name,
        "fieldKey": field_key,
        "dataType": field_type,
        "placeholder": placeholder,
    }
    response = requests.post(url, headers=headers, json=payload)
    result = handle_response(response, f"create custom field '{field_name}'")
    print(f"  [OK] Custom field created: {field_name} (key: {field_key})")
    return result


def deploy_custom_fields(sub_account_id: str, headers: dict) -> None:
    """Create all custom fields required for the MCTB module."""
    print("\n[Step 1] Creating custom fields...")

    fields = [
        {
            "field_name": "Booking Link",
            "field_key": "contact.booking_link",
            "field_type": "TEXT",
            "placeholder": "https://book.yourbusiness.com.au",
        },
        {
            "field_name": "Preferred Callback Time",
            "field_key": "contact.preferred_callback_time",
            "field_type": "TEXT",
            "placeholder": "e.g. Weekday mornings, After 5pm",
        },
    ]

    for field in fields:
        create_custom_field(
            sub_account_id=sub_account_id,
            headers=headers,
            field_name=field["field_name"],
            field_key=field["field_key"],
            field_type=field["field_type"],
            placeholder=field["placeholder"],
        )
        rate_limit_pause()

    print("  [OK] All custom fields created.")


# ---------------------------------------------------------------------------
# Step 2: Create Pipeline
# ---------------------------------------------------------------------------

def deploy_pipeline(sub_account_id: str, headers: dict) -> Optional[str]:
    """
    Create the Lead Recovery opportunity pipeline with 4 stages.

    GHL API: POST /opportunities/pipelines
    Returns the pipeline ID.
    """
    print("\n[Step 2] Creating Lead Recovery pipeline...")

    url = f"{GHL_API_BASE}/opportunities/pipelines"
    payload = {
        "locationId": sub_account_id,
        "name": "Lead Recovery",
        "stages": [
            {
                "name": "Missed Call — Follow Up",
                "position": 0,
            },
            {
                "name": "Engaged via SMS",
                "position": 1,
            },
            {
                "name": "Booked",
                "position": 2,
            },
            {
                "name": "Lost",
                "position": 3,
            },
        ],
    }

    response = requests.post(url, headers=headers, json=payload)
    result = handle_response(response, "create Lead Recovery pipeline")
    pipeline_id = result.get("pipeline", {}).get("id") or result.get("id")
    print(f"  [OK] Pipeline created: Lead Recovery (ID: {pipeline_id})")
    return pipeline_id


# ---------------------------------------------------------------------------
# Step 3: Create SMS Templates
# ---------------------------------------------------------------------------

def create_sms_template(
    sub_account_id: str,
    headers: dict,
    template_name: str,
    template_body: str,
) -> dict:
    """
    Create a saved SMS reply template in a GHL sub-account.

    GHL API: POST /conversations/messages/inbound (templates endpoint)
    Note: GHL stores these as "Custom Responses" or "Saved Replies".
    """
    url = f"{GHL_API_BASE}/locations/{sub_account_id}/customResponses"
    payload = {
        "name": template_name,
        "message": template_body,
        "type": "SMS",
    }
    response = requests.post(url, headers=headers, json=payload)
    result = handle_response(response, f"create SMS template '{template_name}'")
    print(f"  [OK] SMS template created: {template_name}")
    return result


def deploy_sms_templates(
    sub_account_id: str,
    headers: dict,
    business_name: str,
    booking_link: str,
) -> None:
    """Create all three MCTB SMS templates."""
    print("\n[Step 3] Creating SMS templates...")

    templates = [
        {
            "name": "MCTB — Initial Response",
            "body": (
                f"Hi {{{{contact.first_name}}}}, sorry we missed your call at {business_name}! "
                f"We'll call you right back. Or reply here if you prefer a text. — The Team"
            ),
        },
        {
            "name": "MCTB — Follow Up (4hr)",
            "body": (
                f"We still haven't been able to reach you. Is there a better time to call? "
                f"Or tap here to book online: {booking_link} — The Team"
            ),
        },
        {
            "name": "MCTB — Booking Confirmation",
            "body": (
                f"You're locked in! We'll see you on {{{{appointment.date}}}} at {{{{appointment.time}}}}. "
                f"Any questions, just reply here. — {business_name}"
            ),
        },
    ]

    for template in templates:
        create_sms_template(
            sub_account_id=sub_account_id,
            headers=headers,
            template_name=template["name"],
            template_body=template["body"],
        )
        rate_limit_pause()

    print("  [OK] All SMS templates created.")


# ---------------------------------------------------------------------------
# Step 4: Set Sub-Account Custom Values
# ---------------------------------------------------------------------------

def deploy_custom_values(
    sub_account_id: str,
    headers: dict,
    business_name: str,
    booking_link: str,
    owner_phone: str,
) -> None:
    """
    Set sub-account level custom values used in workflow templates.

    GHL API: POST /locations/{locationId}/customValues
    These are location-level (not contact-level) variables.
    """
    print("\n[Step 4] Setting sub-account custom values...")

    url = f"{GHL_API_BASE}/locations/{sub_account_id}/customValues"

    custom_values = [
        {"name": "business_name", "value": business_name},
        {"name": "team_name", "value": "The Team"},
        {"name": "booking_link", "value": booking_link},
        {"name": "owner_phone", "value": owner_phone},
    ]

    for cv in custom_values:
        payload = {"name": cv["name"], "value": cv["value"]}
        response = requests.post(url, headers=headers, json=payload)
        # Custom values may already exist — treat 422/409 as a soft warning, not fatal
        if response.status_code in (422, 409):
            print(f"  [WARN] Custom value '{cv['name']}' may already exist — skipping.")
        else:
            handle_response(response, f"set custom value '{cv['name']}'")
            print(f"  [OK] Custom value set: {cv['name']} = {cv['value']}")
        rate_limit_pause()

    print("  [OK] Custom values configured.")


# ---------------------------------------------------------------------------
# Step 5: Create Workflow via GHL API (note on limitations)
# ---------------------------------------------------------------------------

def print_workflow_manual_instructions(
    business_name: str,
    booking_link: str,
    owner_phone: str,
) -> None:
    """
    GHL does not currently expose a full workflow creation endpoint via API v2
    for complex multi-step automation workflows. The workflow must be created
    manually or imported via a GHL snapshot.

    This function prints the required manual steps and links to the spec.
    """
    print("\n[Step 5] Workflow creation — manual step required")
    print("  -------------------------------------------------------")
    print("  NOTE: The GHL API v2 does not support programmatic creation")
    print("  of complex automation workflows with conditions and branches.")
    print("")
    print("  To deploy the MCTB workflow:")
    print("  Option A — Import snapshot (recommended):")
    print("    1. Request the MCTB snapshot from the ReceptionistAI team")
    print("    2. In GHL Agency > Snapshots, import the snapshot")
    print("    3. Apply to this sub-account")
    print(f"    4. Update custom values (already set above):")
    print(f"       - business_name: {business_name}")
    print(f"       - booking_link: {booking_link}")
    print(f"       - owner_phone: {owner_phone}")
    print("")
    print("  Option B — Build manually in GHL:")
    print("    Follow the complete spec in MCTB_SNAPSHOT_SPEC.md")
    print("    Sub-account > Automation > Workflows > New Workflow")
    print("")
    print("  The pipeline, custom fields, and SMS templates have been")
    print("  created automatically by this script. Only the workflow")
    print("  itself requires the manual step above.")
    print("  -------------------------------------------------------")


# ---------------------------------------------------------------------------
# Main Deployment Function
# ---------------------------------------------------------------------------

def deploy_mctb(
    sub_account_id: str,
    business_name: str,
    booking_link: str,
    owner_phone: str,
) -> None:
    """
    Full MCTB module deployment to a GHL sub-account.

    Steps:
    1. Create custom fields (booking_link, preferred_callback_time)
    2. Create Lead Recovery pipeline with 4 stages
    3. Create SMS templates (initial, follow-up, confirmation)
    4. Set sub-account custom values
    5. Print workflow manual instructions
    """
    api_key = get_agency_api_key()
    headers = build_headers(api_key)

    print("\n================================================")
    print("  MCTB Module Deployment — ReceptionistAI")
    print("================================================")
    print(f"  Sub-Account ID:  {sub_account_id}")
    print(f"  Business Name:   {business_name}")
    print(f"  Booking Link:    {booking_link}")
    print(f"  Owner Phone:     {owner_phone}")
    print("================================================\n")

    # Step 1 — Custom fields
    deploy_custom_fields(sub_account_id, headers)

    # Step 2 — Pipeline
    pipeline_id = deploy_pipeline(sub_account_id, headers)

    # Step 3 — SMS templates
    deploy_sms_templates(sub_account_id, headers, business_name, booking_link)

    # Step 4 — Custom values
    deploy_custom_values(sub_account_id, headers, business_name, booking_link, owner_phone)

    # Step 5 — Workflow instructions (manual)
    print_workflow_manual_instructions(business_name, booking_link, owner_phone)

    # Deployment summary
    print("\n================================================")
    print("  DEPLOYMENT SUMMARY")
    print("================================================")
    print(f"  Sub-Account:       {sub_account_id}")
    print(f"  Custom Fields:     booking_link, preferred_callback_time  [CREATED]")
    print(f"  Pipeline:          Lead Recovery (ID: {pipeline_id})  [CREATED]")
    print(f"  Pipeline Stages:   Missed Call / Engaged / Booked / Lost  [CREATED]")
    print(f"  SMS Templates:     Initial, Follow-Up, Confirmation  [CREATED]")
    print(f"  Custom Values:     business_name, team_name, booking_link, owner_phone  [SET]")
    print(f"  Workflow:          MANUAL STEP REQUIRED (see instructions above)")
    print("================================================")
    print("\n  MCTB deployment complete. Activate the workflow after")
    print("  building or importing it per the instructions above.\n")


# ---------------------------------------------------------------------------
# CLI Entry Point
# ---------------------------------------------------------------------------

def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description=(
            "Deploy the MCTB (Missed Call Text Back) module to a GHL sub-account.\n"
            "Requires GHL_AGENCY_API_KEY environment variable."
        ),
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  python ghl_mctb_deploy.py \\
    --sub-account-id abc123xyz \\
    --business-name "Precision Plumbing" \\
    --booking-link "https://book.precisionplumbing.com.au" \\
    --owner-phone "+61412345678"
        """,
    )
    parser.add_argument(
        "--sub-account-id",
        required=True,
        help="GHL sub-account (location) ID to deploy to",
    )
    parser.add_argument(
        "--business-name",
        required=True,
        help='Client business trading name (e.g. "Precision Plumbing")',
    )
    parser.add_argument(
        "--booking-link",
        required=True,
        help="Client online booking URL (e.g. https://book.client.com.au)",
    )
    parser.add_argument(
        "--owner-phone",
        required=True,
        help="Business owner phone for internal MCTB alert notifications (E.164 format, e.g. +61412345678)",
    )
    return parser.parse_args()


if __name__ == "__main__":
    args = parse_args()
    deploy_mctb(
        sub_account_id=args.sub_account_id,
        business_name=args.business_name,
        booking_link=args.booking_link,
        owner_phone=args.owner_phone,
    )
