#!/usr/bin/env python3
"""
Slow Day Workflow — end-to-end pipeline for slow-day promo campaigns.

Pipeline:
  1. Parse USchedule calendar email → detect if tomorrow is slow
  2. Generate a unique promo code
  3. Render the slow-day-promo HTML email template
  4. Draft a MailerLite campaign targeting the "Slow Day" group
  5. Output a Telegram approval message for Larry

This script does NOT send anything to customers. It prepares the campaign
and outputs what needs Larry's approval.

Usage:
    # From email file:
    python3 slow_day_workflow.py --email path/to/uschedule-email.txt

    # From stdin (piped from Gmail hook):
    echo "$EMAIL_BODY" | python3 slow_day_workflow.py --stdin

    # Dry run (no MailerLite draft, just output):
    python3 slow_day_workflow.py --email email.txt --dry-run

    # Override discount:
    python3 slow_day_workflow.py --email email.txt --discount 15
"""

from __future__ import annotations

import argparse
import json
import os
import sys
import urllib.request
import urllib.error
from datetime import datetime
from pathlib import Path
from typing import Optional, Dict

# Add scripts dir to path for local imports
SCRIPTS_DIR = Path(__file__).resolve().parent
WORKSPACE = SCRIPTS_DIR.parent
sys.path.insert(0, str(SCRIPTS_DIR))

from slow_day_detector import analyze, parse_email_file
from promo_code_generator import create_promo

# Paths
TEMPLATE_PATH = WORKSPACE / "02_Customer_Communication" / "email-templates" / "slow-day-promo.html"
ENV_PATH = WORKSPACE / "automation" / "n8n" / ".env"
OUTPUT_DIR = WORKSPACE / "12_Output"

# Swing Shift hours (default)
DEFAULT_OPEN = "10:00 AM"
DEFAULT_CLOSE = "10:00 PM"
DEFAULT_DISCOUNT = 20


def load_env(env_path: Path) -> dict:
    """Load key=value pairs from .env file."""
    env = {}
    if not env_path.exists():
        return env
    for line in env_path.read_text().splitlines():
        line = line.strip()
        if not line or line.startswith("#"):
            continue
        if "=" in line:
            key, _, val = line.partition("=")
            env[key.strip()] = val.strip()
    return env


def render_template(
    template_path: Path,
    day_name: str,
    promo_code: str,
    discount: int,
    open_time: str = DEFAULT_OPEN,
    close_time: str = DEFAULT_CLOSE,
) -> str:
    """Render the slow-day promo HTML template with values."""
    html = template_path.read_text(encoding="utf-8")
    html = html.replace("{{day_name}}", day_name)
    html = html.replace("{{promo_code}}", promo_code)
    html = html.replace("{{discount}}", str(discount))
    html = html.replace("{{open_time}}", open_time)
    html = html.replace("{{close_time}}", close_time)
    return html


def create_mailerlite_campaign(
    api_key: str,
    group_id: str,
    subject: str,
    html_content: str,
    campaign_name: str,
) -> dict | None:
    """
    Create a draft campaign in MailerLite via API.
    Returns campaign data or None on failure.
    """
    url = "https://connect.mailerlite.com/api/campaigns"
    payload = {
        "name": campaign_name,
        "type": "regular",
        "emails": [{
            "subject": subject,
            "from_name": "Swing Shift Golf Club",
            "from": "ops@theswingshift.golf",
            "content": html_content,
        }],
        "groups": [group_id],
    }

    data = json.dumps(payload).encode("utf-8")
    req = urllib.request.Request(
        url,
        data=data,
        method="POST",
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}",
            "Accept": "application/json",
        },
    )

    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        error_body = e.read().decode("utf-8", errors="replace")
        return {"error": True, "status": e.code, "body": error_body}
    except Exception as e:
        return {"error": True, "message": str(e)}


def build_telegram_approval_message(
    day_name: str,
    target_date: str,
    booking_count: int,
    utilization_pct: float,
    promo_code: str,
    discount: int,
    subscriber_count: int,
    campaign_id: str | None = None,
) -> str:
    """Build the concise Telegram message for Larry's approval."""
    status = "DRAFT READY" if campaign_id else "DRY RUN"
    return (
        f"📊 Slow Day Detected — {day_name} ({target_date})\n"
        f"Bookings: {booking_count} | Utilization: {utilization_pct}%\n\n"
        f"🎟 Promo: {promo_code} ({discount}% off)\n"
        f"📧 Target: Slow Day group ({subscriber_count} subscribers)\n"
        f"Status: {status}\n\n"
        f"Reply YES to send, NO to cancel."
    )


def save_workflow_result(result: dict) -> Path:
    """Save workflow result to output directory for audit trail."""
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    ts = datetime.now().strftime("%Y%m%d_%H%M%S")
    out_path = OUTPUT_DIR / f"slow_day_workflow_{ts}.json"
    out_path.write_text(json.dumps(result, indent=2, default=str))
    return out_path


def run_workflow(
    email_text: str,
    discount: int = DEFAULT_DISCOUNT,
    threshold_pct: int = 50,
    dry_run: bool = False,
) -> dict:
    """Execute the full slow-day workflow pipeline."""
    result = {
        "timestamp": datetime.now().isoformat(),
        "dry_run": dry_run,
        "steps": {},
    }

    # Step 1: Detect slow day
    detection = analyze(email_text, threshold_pct)
    result["steps"]["detection"] = detection

    if not detection["is_slow_day"]:
        result["outcome"] = "not_slow_day"
        result["message"] = (
            f"{detection['day_name']} has {detection['booking_count']} bookings "
            f"({detection['utilization_pct']}% utilization) — above {threshold_pct}% threshold. "
            f"No promo needed."
        )
        return result

    # Step 2: Generate promo code
    promo = create_promo(
        discount=discount,
        campaign="slow-day",
        valid_hours=24,
        notes=f"Auto-generated for {detection['target_date']}",
    )
    result["steps"]["promo"] = promo

    # Step 3: Render email template
    if TEMPLATE_PATH.exists():
        html = render_template(
            TEMPLATE_PATH,
            day_name=detection["day_name"],
            promo_code=promo["code"],
            discount=discount,
        )
        result["steps"]["template"] = {"rendered": True, "length": len(html)}
    else:
        html = None
        result["steps"]["template"] = {"rendered": False, "error": "Template not found"}

    # Step 4: Create MailerLite draft (unless dry run)
    campaign_id = None
    env = load_env(ENV_PATH)
    api_key = env.get("MAILERLITE_API_KEY", "")
    group_id = env.get("MAILERLITE_GROUP_SLOW_DAY", "182257596076394271")

    if not dry_run and api_key and html:
        subject = f"Open bays {detection['day_name']} — {promo['code']} for {discount}% off"
        campaign_name = f"Slow Day {detection['target_date']} — {promo['code']}"
        ml_result = create_mailerlite_campaign(
            api_key=api_key,
            group_id=group_id,
            subject=subject,
            html_content=html,
            campaign_name=campaign_name,
        )
        result["steps"]["mailerlite"] = ml_result
        if ml_result and not ml_result.get("error"):
            campaign_id = ml_result.get("data", {}).get("id")
    else:
        result["steps"]["mailerlite"] = {
            "skipped": True,
            "reason": "dry_run" if dry_run else ("no_api_key" if not api_key else "no_template"),
        }

    # Step 5: Build approval message
    approval_msg = build_telegram_approval_message(
        day_name=detection["day_name"],
        target_date=detection["target_date"],
        booking_count=detection["booking_count"],
        utilization_pct=detection["utilization_pct"],
        promo_code=promo["code"],
        discount=discount,
        subscriber_count=312,  # from current slow-day group
        campaign_id=campaign_id,
    )
    result["steps"]["approval_message"] = approval_msg
    result["outcome"] = "slow_day_detected"
    result["message"] = approval_msg

    # Save audit trail
    out_path = save_workflow_result(result)
    result["audit_file"] = str(out_path)

    return result


def main():
    parser = argparse.ArgumentParser(description="Slow day promo workflow")
    parser.add_argument("--email", help="Path to USchedule calendar email file")
    parser.add_argument("--stdin", action="store_true", help="Read email from stdin")
    parser.add_argument("--discount", type=int, default=DEFAULT_DISCOUNT,
                        help=f"Discount %% (default: {DEFAULT_DISCOUNT})")
    parser.add_argument("--threshold", type=int, default=50,
                        help="Slow day threshold %% (default: 50)")
    parser.add_argument("--dry-run", action="store_true",
                        help="Skip MailerLite API call, just output results")
    args = parser.parse_args()

    if args.stdin:
        email_text = sys.stdin.read()
    elif args.email:
        email_text = parse_email_file(args.email)
    else:
        parser.print_help()
        sys.exit(1)

    result = run_workflow(
        email_text=email_text,
        discount=args.discount,
        threshold_pct=args.threshold,
        dry_run=args.dry_run,
    )

    print(json.dumps(result, indent=2, default=str))

    if result["outcome"] == "slow_day_detected":
        sys.exit(0)
    else:
        sys.exit(2)


if __name__ == "__main__":
    main()
