"""
seed_flow_templates.py — Seed initial Flow Templates (system-owned).

Migrates the 4 hardcoded project templates (fiber_install, phone_service,
move_service, repair_service) from apps/ops/src/config/project-templates.js
into Flow Template docs (is_system=1).

Also seeds:
  - residential_onboarding  : runs on_contract_signed, ties install + reminders
  - quotation_follow_up     : runs on_quotation_created, sends reminders

Run (inside backend container):
  docker exec -u frappe erpnext-backend-1 bash -c \\
    'cd /home/frappe/frappe-bench/sites && \\
     /home/frappe/frappe-bench/env/bin/python -c \\
     "import frappe; frappe.init(site=\\"erp.gigafibre.ca\\"); frappe.connect(); \\
      from seed_flow_templates import seed_all; seed_all()"'

Idempotent: skips templates that already exist by template_name.
"""

import json
import frappe


# Flow definition schema:
#   {
#     "version": 1,
#     "trigger": { "event": "...", "condition": "" },
#     "variables": {...},        # flow-level defaults
#     "steps": [ <Step>, ... ]
#   }
#
# Step schema:
#   {
#     "id": "step_xxx",          # stable ID
#     "kind": "dispatch_job"|"issue"|"notify"|"webhook"|"erp_update"|"wait"|"condition"|"subscription_activate",
#     "label": "...",             # human-readable
#     "parent_id": null | "step_yyy",
#     "branch": null | "yes" | "no" | custom,
#     "depends_on": ["step_xxx"], # array of step IDs; empty = run at flow start
#     "trigger": {                # when to execute this step
#       "type": "on_flow_start" | "on_prev_complete" | "after_delay" | "on_date" | "on_webhook" | "manual",
#       "delay_hours": 24,        # for after_delay
#       "delay_days": 7,          # for after_delay
#       "at": "2026-05-01T09:00", # for on_date
#     },
#     "payload": { ... }          # kind-specific fields (see below)
#   }
#
# Payloads by kind:
#   dispatch_job: { subject, job_type, priority, duration_h, assigned_group,
#                   on_open_webhook, on_close_webhook, merge_key }
#   issue:        { subject, description, priority, raised_by, issue_type }
#   notify:       { channel: "sms"|"email", to, template_id, subject, body }
#   webhook:      { url, method: "POST", headers, body_template }
#   erp_update:   { doctype, docname_ref, fields: {field: value} }
#   wait:         {}  (uses trigger.delay_hours/delay_days)
#   condition:    { field, op: "==|!=|<|>|<=|>=|in|not_in", value }
#                 Children on branch "yes" / "no"
#   subscription_activate: { subscription_ref }


# ---------------------------------------------------------------------------
# Helper builders (keep seed JSON readable)
# ---------------------------------------------------------------------------

def _dispatch_step(sid, label, subject, job_type, priority, duration_h,
                   group, depends_on=None, merge_key=None,
                   open_wh="", close_wh=""):
    return {
        "id": sid,
        "kind": "dispatch_job",
        "label": label,
        "parent_id": None,
        "branch": None,
        "depends_on": depends_on or [],
        "trigger": {"type": "on_prev_complete" if depends_on else "on_flow_start"},
        "payload": {
            "subject": subject,
            "job_type": job_type,
            "priority": priority,
            "duration_h": duration_h,
            "assigned_group": group,
            "merge_key": merge_key or sid,
            "on_open_webhook": open_wh,
            "on_close_webhook": close_wh,
        },
    }


def _notify_step(sid, label, channel, template_id, depends_on=None,
                 trigger_type="on_prev_complete", delay_hours=None):
    trig = {"type": trigger_type}
    if delay_hours:
        trig["delay_hours"] = delay_hours
    return {
        "id": sid,
        "kind": "notify",
        "label": label,
        "parent_id": None,
        "branch": None,
        "depends_on": depends_on or [],
        "trigger": trig,
        "payload": {
            "channel": channel,
            "to": "{{customer.primary_phone}}" if channel == "sms" else "{{customer.email_id}}",
            "template_id": template_id,
        },
    }


def _issue_step(sid, label, subject, depends_on=None):
    return {
        "id": sid,
        "kind": "issue",
        "label": label,
        "parent_id": None,
        "branch": None,
        "depends_on": depends_on or [],
        "trigger": {"type": "on_prev_complete" if depends_on else "on_flow_start"},
        "payload": {
            "subject": subject,
            "priority": "Medium",
            "issue_type": "Suivi",
        },
    }


def _wait_step(sid, label, delay_hours=None, delay_days=None, depends_on=None):
    trig = {"type": "after_delay"}
    if delay_hours:
        trig["delay_hours"] = delay_hours
    if delay_days:
        trig["delay_days"] = delay_days
    return {
        "id": sid,
        "kind": "wait",
        "label": label,
        "parent_id": None,
        "branch": None,
        "depends_on": depends_on or [],
        "trigger": trig,
        "payload": {},
    }


# ---------------------------------------------------------------------------
# Seed definitions
# ---------------------------------------------------------------------------

def _tpl_fiber_install():
    return {
        "template_name": "Installation fibre résidentielle",
        "category": "Internet",
        "applies_to": "Service Contract",
        "icon": "cable",
        "description": "Vérification pré-install, installation, activation, test de débit",
        "is_system": 1,
        "trigger_event": "manual",
        "flow_definition": {
            "version": 1,
            "trigger": {"event": "manual", "condition": ""},
            "variables": {},
            "steps": [
                _dispatch_step("s1", "Vérification pré-installation",
                    "Vérification pré-installation (éligibilité & OLT)",
                    "Autre", "medium", 0.5, "Admin", merge_key="fiber_pre_check"),
                _dispatch_step("s2", "Installation fibre",
                    "Installation fibre chez le client",
                    "Installation", "high", 3, "Tech Targo",
                    depends_on=["s1"], merge_key="fiber_install_visit"),
                _dispatch_step("s3", "Activation & config ONT",
                    "Activation du service & configuration ONT",
                    "Installation", "high", 0.5, "Admin",
                    depends_on=["s2"], merge_key="fiber_activation"),
                _dispatch_step("s4", "Test de débit",
                    "Test de débit & validation client",
                    "Dépannage", "medium", 0.5, "Tech Targo",
                    depends_on=["s3"], merge_key="fiber_speed_test"),
            ],
        },
    }


def _tpl_phone_service():
    return {
        "template_name": "Service téléphonique résidentiel",
        "category": "Téléphonie",
        "applies_to": "Service Contract",
        "icon": "phone_in_talk",
        "description": "Importation du numéro, installation fibre, portage du numéro",
        "is_system": 1,
        "trigger_event": "manual",
        "flow_definition": {
            "version": 1,
            "trigger": {"event": "manual", "condition": ""},
            "variables": {},
            "steps": [
                _dispatch_step("s1", "Importer numéro",
                    "Importer le numéro de téléphone",
                    "Autre", "medium", 0.5, "Admin", merge_key="port_phone_request"),
                _dispatch_step("s2", "Installation fibre",
                    "Installation fibre chez le client",
                    "Installation", "high", 3, "Tech Targo",
                    depends_on=["s1"], merge_key="fiber_install_visit"),
                _dispatch_step("s3", "Portage numéro",
                    "Portage du numéro vers Gigafibre",
                    "Autre", "medium", 0.5, "Admin",
                    depends_on=["s2"], merge_key="port_phone_execute"),
                _dispatch_step("s4", "Test téléphonie",
                    "Validation et test du service téléphonique",
                    "Dépannage", "medium", 0.5, "Tech Targo",
                    depends_on=["s3"], merge_key="phone_service_test"),
            ],
        },
    }


def _tpl_move_service():
    return {
        "template_name": "Déménagement de service",
        "category": "Déménagement",
        "applies_to": "Service Contract",
        "icon": "local_shipping",
        "description": "Retrait ancien site, installation nouveau site, transfert abonnement",
        "is_system": 1,
        "trigger_event": "manual",
        "flow_definition": {
            "version": 1,
            "trigger": {"event": "manual", "condition": ""},
            "variables": {},
            "steps": [
                _dispatch_step("s1", "Préparation",
                    "Préparation déménagement (vérifier éligibilité nouveau site)",
                    "Autre", "medium", 0.5, "Admin", merge_key="move_prep"),
                _dispatch_step("s2", "Retrait ancien site",
                    "Retrait équipement ancien site",
                    "Retrait", "medium", 1, "Tech Targo",
                    depends_on=["s1"], merge_key="move_removal"),
                _dispatch_step("s3", "Installation nouveau site",
                    "Installation au nouveau site",
                    "Installation", "high", 3, "Tech Targo",
                    depends_on=["s2"], merge_key="fiber_install_visit"),
                _dispatch_step("s4", "Transfert abonnement",
                    "Transfert abonnement & mise à jour adresse",
                    "Autre", "medium", 0.5, "Admin",
                    depends_on=["s3"], merge_key="move_transfer"),
            ],
        },
    }


def _tpl_repair_service():
    return {
        "template_name": "Réparation service client",
        "category": "Dépannage",
        "applies_to": "Issue",
        "icon": "build",
        "description": "Diagnostic, intervention terrain, validation",
        "is_system": 1,
        "trigger_event": "on_issue_opened",
        "flow_definition": {
            "version": 1,
            "trigger": {"event": "on_issue_opened", "condition": ""},
            "variables": {},
            "steps": [
                _dispatch_step("s1", "Diagnostic à distance",
                    "Diagnostic à distance",
                    "Dépannage", "high", 0.5, "Admin", merge_key="repair_diag"),
                _dispatch_step("s2", "Intervention terrain",
                    "Intervention terrain",
                    "Réparation", "high", 2, "Tech Targo",
                    depends_on=["s1"], merge_key="repair_visit"),
                _dispatch_step("s3", "Validation client",
                    "Validation & suivi client",
                    "Dépannage", "medium", 0.5, "Admin",
                    depends_on=["s2"], merge_key="repair_validate"),
            ],
        },
    }


def _tpl_residential_onboarding():
    """
    Flow complet déclenché à la signature du Service Contract résidentiel.
    Ferme la boucle CTR-00004 : installation + rappels + satisfaction + renouvellement.
    """
    return {
        "template_name": "Onboarding résidentiel (post-signature)",
        "category": "Onboarding",
        "applies_to": "Service Contract",
        "icon": "rocket_launch",
        "description": "Flow complet après signature: SMS bienvenue, installation, test, survey, renouvellement",
        "is_system": 1,
        "trigger_event": "on_contract_signed",
        "trigger_condition": "contract.contract_type == 'Résidentiel'",
        "flow_definition": {
            "version": 1,
            "trigger": {
                "event": "on_contract_signed",
                "condition": "contract.contract_type == 'Résidentiel'",
            },
            "variables": {},
            "steps": [
                # Immédiat — accueil
                _notify_step("welcome_sms", "SMS de bienvenue",
                    channel="sms", template_id="welcome_residential",
                    trigger_type="on_flow_start"),
                _issue_step("onboarding_ticket",
                    "Ticket suivi onboarding",
                    "Onboarding résidentiel — suivi client"),

                # Installation (dépend de rien, démarre immédiatement)
                _dispatch_step("install", "Installation fibre",
                    "Installation fibre chez le client",
                    "Installation", "high", 3, "Tech Targo",
                    merge_key="fiber_install_visit",
                    open_wh="", close_wh=""),

                # Activation abonnement après installation complétée
                {
                    "id": "activate_sub",
                    "kind": "subscription_activate",
                    "label": "Activer l'abonnement",
                    "parent_id": None,
                    "branch": None,
                    "depends_on": ["install"],
                    "trigger": {"type": "on_prev_complete"},
                    "payload": {"subscription_ref": "{{contract.subscription}}"},
                },

                # SMS confirmation service actif
                _notify_step("active_sms", "SMS service actif",
                    channel="sms", template_id="service_activated",
                    depends_on=["activate_sub"]),

                # Survey satisfaction 24h après install
                _wait_step("wait_24h", "Attendre 24h après install",
                    delay_hours=24, depends_on=["install"]),
                _notify_step("survey_sms", "SMS sondage satisfaction",
                    channel="sms", template_id="satisfaction_survey",
                    depends_on=["wait_24h"]),

                # Rappel renouvellement à 11 mois (anticipation du renouvel à 12 mois)
                _wait_step("wait_11m", "Attendre 11 mois",
                    delay_days=330, depends_on=["activate_sub"]),
                _issue_step("renewal_ticket",
                    "Ticket renouvellement",
                    "Rappel: contrat arrive à échéance dans 1 mois",
                    depends_on=["wait_11m"]),
            ],
        },
    }


def _tpl_quotation_follow_up():
    """Relance douce 48h après envoi de quotation non acceptée."""
    return {
        "template_name": "Relance quotation non signée",
        "category": "Custom",
        "applies_to": "Quotation",
        "icon": "mail",
        "description": "SMS de rappel 48h après envoi d'un devis résidentiel",
        "is_system": 1,
        "trigger_event": "on_quotation_created",
        "trigger_condition": "quotation.status == 'Submitted'",
        "flow_definition": {
            "version": 1,
            "trigger": {
                "event": "on_quotation_created",
                "condition": "quotation.status == 'Submitted'",
            },
            "variables": {},
            "steps": [
                _wait_step("wait_48h", "Attendre 48h", delay_hours=48),
                _notify_step("reminder_sms",
                    "SMS rappel devis", channel="sms",
                    template_id="quotation_reminder",
                    depends_on=["wait_48h"]),
            ],
        },
    }


# ---------------------------------------------------------------------------
# Seeder
# ---------------------------------------------------------------------------

SEEDS = [
    _tpl_fiber_install,
    _tpl_phone_service,
    _tpl_move_service,
    _tpl_repair_service,
    _tpl_residential_onboarding,
    _tpl_quotation_follow_up,
]


def _count_steps(flow_def):
    return len(flow_def.get("steps", []))


def _upsert(tpl):
    name = tpl["template_name"]
    exists = frappe.db.exists("Flow Template", {"template_name": name})
    flow_def_json = json.dumps(tpl["flow_definition"], ensure_ascii=False, indent=2)
    step_count = _count_steps(tpl["flow_definition"])

    if exists:
        doc = frappe.get_doc("Flow Template", exists)
        # Only update is_system=1 seeds automatically
        if not doc.is_system:
            print(f"  SKIP {name!r} — exists as user-edited (is_system=0)")
            return
        doc.update({
            "category": tpl["category"],
            "applies_to": tpl["applies_to"],
            "icon": tpl.get("icon", "account_tree"),
            "description": tpl.get("description", ""),
            "trigger_event": tpl.get("trigger_event", "manual"),
            "trigger_condition": tpl.get("trigger_condition", ""),
            "flow_definition": flow_def_json,
            "step_count": step_count,
            "version": (doc.version or 0) + 1,
        })
        doc.save(ignore_permissions=True)
        print(f"  UPDATED {name!r} -> v{doc.version}, {step_count} steps")
        return

    doc = frappe.get_doc({
        "doctype": "Flow Template",
        "template_name": name,
        "category": tpl["category"],
        "applies_to": tpl["applies_to"],
        "icon": tpl.get("icon", "account_tree"),
        "is_active": 1,
        "is_system": tpl.get("is_system", 0),
        "version": 1,
        "description": tpl.get("description", ""),
        "trigger_event": tpl.get("trigger_event", "manual"),
        "trigger_condition": tpl.get("trigger_condition", ""),
        "flow_definition": flow_def_json,
        "step_count": step_count,
    })
    doc.insert(ignore_permissions=True)
    print(f"  CREATED {name!r} -> {doc.name}, {step_count} steps")


def seed_all():
    for factory in SEEDS:
        tpl = factory()
        _upsert(tpl)
    frappe.db.commit()
    print(f"\n[OK] Seeded {len(SEEDS)} Flow Templates.")


if __name__ == "__main__":
    seed_all()
