#!/usr/bin/env python3
"""
Launch27 alerts router for Slack.

Purpose:
- Centralize Launch27-related operational alerts into one channel
- Keep message formatting consistent
- Make it easy for other scripts/crons to post alerts without hard-coding Slack payloads everywhere

Usage examples:
  python3 scripts/launch27-alerts.py \
    --type payment_failure \
    --severity high \
    --title "Booking needs charge" \
    --body "Launch27 notice says 1 booking still needs to be charged." \
    --booking-id 77557

  python3 scripts/launch27-alerts.py \
    --type unassigned_booking \
    --severity critical \
    --title "Tomorrow booking has no contractor" \
    --body "Customer Jane Doe, Apr 17 10:00 AM, Toronto"
"""

import argparse
import json
import os
import sys
import urllib.request
import urllib.error
from datetime import datetime

SECRETS_DIR = os.path.expanduser("~/.openclaw/secrets")
SLACK_TOKEN_FILE = os.path.join(SECRETS_DIR, "slack-token.txt")
DEFAULT_CHANNEL = "C0APXMHJWCR"  # temporary default: ops-internal until dedicated channel ID is confirmed in Slack

SEVERITY_META = {
    "critical": {"emoji": ":red_circle:", "label": "CRITICAL", "color": "#d92d20"},
    "high": {"emoji": ":large_orange_circle:", "label": "HIGH", "color": "#f79009"},
    "medium": {"emoji": ":large_yellow_circle:", "label": "MEDIUM", "color": "#f2c94c"},
    "low": {"emoji": ":large_blue_circle:", "label": "LOW", "color": "#2e90fa"},
}


def read_secret(path: str) -> str:
    with open(path) as f:
        return f.read().strip()


def post_to_slack(token: str, payload: dict) -> dict:
    req = urllib.request.Request(
        "https://slack.com/api/chat.postMessage",
        data=json.dumps(payload).encode(),
        headers={
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
            "User-Agent": "Harvey Launch27 Alerts/1.0",
        },
    )
    with urllib.request.urlopen(req, timeout=20) as resp:
        return json.loads(resp.read().decode())


def build_message(args: argparse.Namespace) -> dict:
    meta = SEVERITY_META[args.severity]
    title = f"{meta['emoji']} Launch27 Alert, {meta['label']} - {args.title}"

    details = [
        f"*Type:* `{args.type}`",
        f"*Time:* {datetime.now().strftime('%Y-%m-%d %H:%M')}",
    ]
    if args.booking_id:
        details.append(f"*Booking ID:* `{args.booking_id}`")
    if args.customer:
        details.append(f"*Customer:* {args.customer}")
    if args.when:
        details.append(f"*When:* {args.when}")
    if args.source:
        details.append(f"*Source:* {args.source}")
    if args.link:
        details.append(f"*Link:* {args.link}")

    text = title + "\n" + "\n".join(details) + "\n\n" + args.body

    return {
        "channel": args.channel,
        "text": text,
        "unfurl_links": False,
        "unfurl_media": False,
        "attachments": [
            {
                "color": meta["color"],
                "mrkdwn_in": ["text"],
                "text": args.body,
                "footer": "Harvey • Launch27 monitor",
            }
        ],
    }


def parse_args() -> argparse.Namespace:
    p = argparse.ArgumentParser()
    p.add_argument("--type", required=True, help="Alert type, ex: payment_failure, booking_error, unassigned_booking")
    p.add_argument("--severity", choices=SEVERITY_META.keys(), default="medium")
    p.add_argument("--title", required=True)
    p.add_argument("--body", required=True)
    p.add_argument("--booking-id")
    p.add_argument("--customer")
    p.add_argument("--when")
    p.add_argument("--source")
    p.add_argument("--link")
    p.add_argument("--channel", default=DEFAULT_CHANNEL)
    return p.parse_args()


def main() -> int:
    args = parse_args()
    try:
        token = read_secret(SLACK_TOKEN_FILE)
        payload = build_message(args)
        result = post_to_slack(token, payload)
        if not result.get("ok"):
            print(json.dumps(result, indent=2), file=sys.stderr)
            return 1
        print(f"Posted Launch27 alert to {args.channel}: {result.get('ts')}")
        return 0
    except FileNotFoundError:
        print(f"Missing Slack token at {SLACK_TOKEN_FILE}", file=sys.stderr)
        return 1
    except urllib.error.HTTPError as e:
        body = e.read().decode(errors="replace")
        print(f"Slack HTTP error {e.code}: {body}", file=sys.stderr)
        return 1
    except Exception as e:
        print(f"Error posting Launch27 alert: {e}", file=sys.stderr)
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
