"""
WhatsApp Template Registry
--------------------------
Single source of truth for ALL approved Meta WhatsApp templates.

How to add a new template:
1.  Get the template approved in Meta Business Manager.
2.  Add an entry under TEMPLATES with:
      - meta_name      : exact name as it appears in Meta
      - language_code  : he / he_IL / en / en_US …
      - friendly_name  : shown in the frontend dropdown
      - description    : optional, for documentation
      - header_params  : ordered list of variable keys sent in the HEADER component
                         (empty list [] if the template has no header variables)
      - body_params    : ordered list of variable keys sent in the BODY component
      - fallbacks      : dict {key: default_string} used when the caller doesn't
                         provide a value for that key

The backend will:
  - Look up the template by its registry key (e.g. "wedding_invitation")
  - Build the Meta payload header/body param lists in exact declaration order
  - Apply fallbacks for any missing keys
  - Validate total param count == len(header_params) + len(body_params)

IMPORTANT: param order in header_params / body_params MUST match the
           {{1}}, {{2}}, … placeholder order inside the Meta template.
"""

import json
import os
from typing import Dict, Any

# ── Custom templates file ─────────────────────────────────────────────────────

CUSTOM_TEMPLATES_FILE = os.path.join(os.path.dirname(__file__), "custom_templates.json")


def load_custom_templates() -> Dict[str, Dict[str, Any]]:
    """Load user-created templates from the JSON store."""
    try:
        with open(CUSTOM_TEMPLATES_FILE, "r", encoding="utf-8") as f:
            return json.load(f)
    except (FileNotFoundError, json.JSONDecodeError):
        return {}


def save_custom_templates(data: Dict[str, Dict[str, Any]]) -> None:
    """Persist custom templates to the JSON store."""
    with open(CUSTOM_TEMPLATES_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)


def get_all_templates() -> Dict[str, Dict[str, Any]]:
    """Return merged dict: built-in TEMPLATES + user custom templates."""
    merged = dict(TEMPLATES)
    merged.update(load_custom_templates())
    return merged


def add_custom_template(key: str, template: Dict[str, Any]) -> None:
    """Add or overwrite a custom template (cannot replace built-ins)."""
    if key in TEMPLATES:
        raise ValueError(f"Template key '{key}' is a built-in and cannot be overwritten.")
    data = load_custom_templates()
    data[key] = template
    save_custom_templates(data)


def delete_custom_template(key: str) -> None:
    """Delete a custom template by key. Raises KeyError if not found."""
    if key in TEMPLATES:
        raise ValueError(f"Template key '{key}' is a built-in and cannot be deleted.")
    data = load_custom_templates()
    if key not in data:
        raise KeyError(f"Custom template '{key}' not found.")
    del data[key]
    save_custom_templates(data)


# ── Template registry ─────────────────────────────────────────────────────────

TEMPLATES: Dict[str, Dict[str, Any]] = {

    # ── wedding_invitation ────────────────────────────────────────────────────
    # Approved Hebrew wedding invitation template.
    # Header {{1}}  = guest name (greeting)
    # Body  {{1}}   = guest name  (same, repeated inside body)
    # Body  {{2}}   = groom name
    # Body  {{3}}   = bride name
    # Body  {{4}}   = venue / hall name
    # Body  {{5}}   = event date  (DD/MM)
    # Body  {{6}}   = event time  (HH:mm)
    # Body  {{7}}   = RSVP / guest link URL
    "wedding_invitation": {
        "meta_name": "wedding_invitation",
        "language_code": "he",
        "friendly_name": "הזמנה לחתונה",
        "description": "הזמנה רשמית לאירוע חתונה עם כל פרטי האירוע וקישור RSVP",
        "header_params": ["contact_name"],          # 1 header variable
        "body_params": [                             # 7 body variables
            "contact_name",    # body {{1}}
            "groom_name",      # body {{2}}
            "bride_name",      # body {{3}}
            "venue",           # body {{4}}
            "event_date",      # body {{5}}
            "event_time",      # body {{6}}
            "guest_link",      # body {{7}}
        ],
        "fallbacks": {
            "contact_name": "חבר",
            "groom_name":   "החתן",
            "bride_name":   "הכלה",
            "venue":        "האולם",
            "event_date":   "—",
            "event_time":   "—",
            "guest_link":   "https://invy.dvirlabs.com/guest",
        },
    },

    # ── save_the_date ─────────────────────────────────────────────────────────
    # Shorter "save the date" template — no venue/time details.
    # Create & approve this template in Meta before using it.
    # Header {{1}} = guest name
    # Body  {{1}}  = guest name  (repeated)
    # Body  {{2}}  = groom name
    # Body  {{3}}  = bride name
    # Body  {{4}}  = event date  (DD/MM/YYYY)
    # Body  {{5}}  = guest link
    "save_the_date": {
        "meta_name": "save_the_date",
        "language_code": "he",
        "friendly_name": "שמור את התאריך",
        "description": "הודעת 'שמור את התאריך' קצרה לפני ההזמנה הרשמית",
        "header_params": ["contact_name"],
        "body_params": [
            "contact_name",
            "groom_name",
            "bride_name",
            "event_date",
            "guest_link",
        ],
        "fallbacks": {
            "contact_name": "חבר",
            "groom_name":   "החתן",
            "bride_name":   "הכלה",
            "event_date":   "—",
            "guest_link":   "https://invy.dvirlabs.com/guest",
        },
    },

    # ── reminder_1 ────────────────────────────────────────────────────────────
    # Reminder template sent ~1 week before the event.
    # Header {{1}} = guest name
    # Body  {{1}}  = guest name
    # Body  {{2}}  = event date  (DD/MM)
    # Body  {{3}}  = event time  (HH:mm)
    # Body  {{4}}  = venue
    # Body  {{5}}  = guest link
    "reminder_1": {
        "meta_name": "reminder_1",
        "language_code": "he",
        "friendly_name": "תזכורת לאירוע",
        "description": "תזכורת שתשלח שבוע לפני האירוע",
        "header_params": ["contact_name"],
        "body_params": [
            "contact_name",
            "event_date",
            "event_time",
            "venue",
            "guest_link",
        ],
        "fallbacks": {
            "contact_name": "חבר",
            "event_date":   "—",
            "event_time":   "—",
            "venue":        "האולם",
            "guest_link":   "https://invy.dvirlabs.com/guest",
        },
    },
}


# ── Helper functions ──────────────────────────────────────────────────────────

def get_template(key: str) -> Dict[str, Any]:
    """
    Return the template definition for *key* (checks both built-in + custom).
    Raises KeyError with a helpful message if not found.
    """
    all_tpls = get_all_templates()
    if key not in all_tpls:
        available = ", ".join(all_tpls.keys())
        raise KeyError(
            f"Unknown template key '{key}'. "
            f"Available templates: {available}"
        )
    return all_tpls[key]


def list_templates_for_frontend() -> list:
    """
    Return a list suitable for the frontend dropdown (built-in + custom).
    Each item: {key, friendly_name, meta_name, param_count, language_code, description, is_custom}
    """
    all_tpls = get_all_templates()
    custom_keys = set(load_custom_templates().keys())
    return [
        {
            "key": key,
            "friendly_name": tpl["friendly_name"],
            "meta_name": tpl["meta_name"],
            "language_code": tpl["language_code"],
            "description": tpl.get("description", ""),
            "param_count": len(tpl["header_params"]) + len(tpl["body_params"]),
            "header_param_count": len(tpl["header_params"]),
            "body_param_count": len(tpl["body_params"]),
            "is_custom": key in custom_keys,
            "body_params": tpl["body_params"],
            "header_params": tpl["header_params"],
            "body_text": tpl.get("body_text", ""),
            "header_text": tpl.get("header_text", ""),
            "guest_name_key": tpl.get("guest_name_key", ""),
            "url_button": tpl.get("url_button", None),
        }
        for key, tpl in all_tpls.items()
    ]


def build_params_list(key: str, values: dict) -> tuple:
    """
    Given a template key and a dict of {param_key: value}, return
    (header_params_list, body_params_list) after applying fallbacks.

    Both lists contain plain string values in correct order.
    """
    tpl = get_template(key)  # checks built-in + custom
    fallbacks = tpl.get("fallbacks", {})

    def resolve(param_key: str) -> str:
        raw = values.get(param_key, "")
        val = str(raw).strip() if raw else ""
        if not val:
            val = str(fallbacks.get(param_key, "—")).strip()
        return val

    header_values = [resolve(k) for k in tpl["header_params"]]
    body_values   = [resolve(k) for k in tpl["body_params"]]
    return header_values, body_values
