import type { RequestPayload } from '@inertiajs/core';
import { Link, router } from '@inertiajs/react';
import {
    addEdge,
    Background,
    Controls,
    Handle,
    MarkerType,
    Position,
    ReactFlow,
    useEdgesState,
    useNodesState,
} from '@xyflow/react';
import type {
    Edge as FlowEdge,
    Node as FlowNode,
    NodeProps,
    ReactFlowInstance,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import {
    ArrowLeft,
    BellOff,
    Check,
    ChevronLeft,
    ChevronRight,
    Clock3,
    Copy,
    Download,
    Menu,
    PanelRightClose,
    Upload,
    GitBranch,
    Globe2,
    GraduationCap,
    Mail,
    MessageSquare,
    Save,
    Search,
    Sparkles,
    Table2,
    Trash2,
    UserRoundCog,
    Users,
    Workflow,
} from 'lucide-react';
import * as React from 'react';
import { toast } from 'sonner';

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import {
    index as automationsIndex,
    store as storeAutomation,
    update as updateAutomation,
} from '@/routes/client/automations';

export interface Group {
    id: number;
    name: string;
}

export type ActionType =
    | 'send_message'
    | 'send_email'
    | 'http_request'
    | 'google_sheets'
    | 'assign_agent'
    | 'save_response'
    | 'condition'
    | 'disable_autoreply'
    | 'delay'
    | 'add_to_group'
    | 'remove_from_group'
    | 'lms_action';

export interface Action {
    type: ActionType;
    text?: string;
    subject?: string;
    email_to?: string;
    url?: string;
    method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
    body?: string;
    sheet_name?: string;
    agent_name?: string;
    response_field?: 'notes' | 'var1' | 'var2' | 'var3' | 'var4' | 'var5';
    condition?: string;
    delay_seconds?: number;
    group_id?: number;
    lms_base_url?: string;
    lms_api_key?: string;
    lms_endpoint?:
        | 'auto'
        | 'verify'
        | 'summary'
        | 'courses'
        | 'select_course'
        | 'outline'
        | 'lesson'
        | 'complete_lesson'
        | 'quiz'
        | 'tasks'
        | 'certificates'
        | 'search';
    conditions?: Array<{
        operator: 'contains' | 'equals' | 'starts_with' | 'ends_with';
        value: string;
    }>;
    conditions_relation?: 'AND' | 'OR';
    buttons?: Array<string | { id?: string; title: string }>;
    footer_text?: string;
    header_text?: string;
    list_button?: string;
    list_sections?: Array<{
        title: string;
        rows: Array<{ id: string; title: string; description?: string }>;
    }>;
}

export interface SerializedGraph {
    nodes: Array<{
        id: string;
        type?: string;
        position: { x: number; y: number };
        data: Record<string, string | number | boolean | null>;
    }>;
    edges: Array<{
        id: string;
        source: string;
        target: string;
        type?: string;
        animated?: boolean;
        label?: string;
    }>;
}

export interface AutomationFlow {
    id: number;
    name: string;
    trigger_type: string;
    trigger_keyword?: string;
    trigger_match_type?: 'exact' | 'contains';
    actions: Action[];
    visual_graph?: SerializedGraph | null;
    is_active: boolean;
    created_at: string;
}

interface FlowBuilderProps {
    groups: Group[];
    flow?: AutomationFlow;
}

interface FlowFormData {
    name: string;
    actions: Action[];
    visual_graph: SerializedGraph | null;
}

interface CatalogItem {
    type: ActionType;
    title: string;
    description: string;
    category: 'Messages' | 'Requests' | 'Inputs' | 'Logic' | 'Contacts';
    icon: React.ComponentType<{ className?: string }>;
    color: string;
}

interface FlowTemplate {
    name: string;
    description: string;
    icon: React.ComponentType<{ className?: string }>;
    color: string;
    actions: Array<Partial<Action> & { type: ActionType }>;
    visual_graph?: SerializedGraph;
}

interface FlowNodeData extends Record<string, unknown> {
    title: string;
    subtitle: string;
    color: string;
    actionIndex?: number;
}

const variables = [
    { token: '{{{senderName}}}', label: 'Nama pengirim' },
    { token: '{{{senderMessage}}}', label: 'Isi pesan teks' },
    { token: '{{{senderMobile}}}', label: 'Nomor telepon' },
];

const catalog: CatalogItem[] = [
    {
        type: 'send_message',
        title: 'Kirim Pesan',
        description: 'Kirim pesan WhatsApp otomatis ke pelanggan',
        category: 'Messages',
        icon: MessageSquare,
        color: 'emerald',
    },
    {
        type: 'send_email',
        title: 'Kirim Email',
        description: 'Kirim notifikasi email ke tim atau pelanggan',
        category: 'Messages',
        icon: Mail,
        color: 'violet',
    },
    {
        type: 'http_request',
        title: 'Permintaan HTTP (API)',
        description: 'Panggil webhook atau endpoint API eksternal',
        category: 'Requests',
        icon: Globe2,
        color: 'purple',
    },
    {
        type: 'google_sheets',
        title: 'Google Spreadsheet',
        description: 'Simpan data obrolan ke Google Spreadsheet',
        category: 'Requests',
        icon: Table2,
        color: 'green',
    },
    {
        type: 'assign_agent',
        title: 'Tugaskan Agen CS',
        description: 'Alihkan percakapan ke agen manusia (CS)',
        category: 'Requests',
        icon: UserRoundCog,
        color: 'rose',
    },
    {
        type: 'save_response',
        title: 'Simpan Respons',
        description: 'Rekam dan simpan input balasan pelanggan',
        category: 'Inputs',
        icon: Save,
        color: 'green',
    },
    {
        type: 'condition',
        title: 'Kondisi / Percabangan',
        description: 'Arahkan alur jika kata kunci atau aturan cocok',
        category: 'Logic',
        icon: GitBranch,
        color: 'rose',
    },
    {
        type: 'disable_autoreply',
        title: 'Nonaktifkan Balas Otomatis',
        description: 'Hentikan bot sementara pada titik ini',
        category: 'Logic',
        icon: BellOff,
        color: 'orange',
    },
    {
        type: 'delay',
        title: 'Jeda Waktu (Delay)',
        description: 'Tunggu beberapa detik sebelum lanjut',
        category: 'Logic',
        icon: Clock3,
        color: 'orange',
    },
    {
        type: 'add_to_group',
        title: 'Tambah ke Grup',
        description: 'Tambahkan kontak pelanggan ke grup tertentu',
        category: 'Contacts',
        icon: Users,
        color: 'sky',
    },
    {
        type: 'remove_from_group',
        title: 'Hapus dari Grup',
        description: 'Keluarkan kontak pelanggan dari grup tertentu',
        category: 'Contacts',
        icon: Users,
        color: 'amber',
    },
    {
        type: 'lms_action',
        title: 'LMS Natagara',
        description: 'Integrasi otomatis ke LMS Natagara (Verifikasi, Kelas, Ringkasan, Tugas)',
        category: 'Requests',
        icon: GraduationCap,
        color: 'emerald',
    },
];

const categories: CatalogItem['category'][] = [
    'Messages',
    'Requests',
    'Inputs',
    'Logic',
    'Contacts',
];

const colorClasses: Record<string, string> = {
    emerald: 'bg-emerald-600 text-white',
    violet: 'bg-violet-500 text-white',
    purple: 'bg-purple-500 text-white',
    green: 'bg-green-500 text-white',
    rose: 'bg-rose-500 text-white',
    orange: 'bg-orange-500 text-white',
    sky: 'bg-sky-500 text-white',
    amber: 'bg-amber-500 text-white',
};

function StartNode({ data }: NodeProps<FlowNode<FlowNodeData>>) {
    const nodeData = data as FlowNodeData;

    return (
        <div className="w-[320px] overflow-hidden rounded-[24px] border-2 border-emerald-600 bg-white shadow-2xl shadow-zinc-900/10 dark:bg-zinc-950">
            <div className="bg-emerald-600 px-5 py-4 text-left text-white">
                <div className="text-xl font-black">Mulai Bot</div>
                <div className="text-xs font-semibold text-white/80">
                    {nodeData.subtitle}
                </div>
            </div>
            <div className="space-y-3 p-5 text-left">
                <h3 className="text-sm font-black text-zinc-900 dark:text-zinc-50">
                    Variabel dinamis (klik untuk menyalin)
                </h3>
                {variables.map((variable) => (
                    <button
                        key={variable.token}
                        type="button"
                        className="flex w-full items-center justify-between gap-4 rounded-xl border bg-zinc-50 px-4 py-2 text-left transition hover:border-emerald-400 hover:bg-emerald-50 dark:bg-zinc-900 dark:hover:bg-emerald-950/30"
                        onClick={() => {
                            navigator.clipboard.writeText(variable.token);
                            toast.success('Variabel disalin: ' + variable.token);
                        }}
                    >
                        <Copy className="h-4 w-4 text-zinc-500" />
                        <span>
                            <span className="block font-mono text-sm font-black text-emerald-700 dark:text-emerald-300">
                                {variable.token}
                            </span>
                            <span className="block text-xs font-semibold text-zinc-500 dark:text-zinc-400">
                                {variable.label}
                            </span>
                        </span>
                    </button>
                ))}
            </div>
            <Handle
                className="!h-4 !w-4 !border-2 !border-white !bg-emerald-600"
                position={Position.Right}
                type="source"
            />
        </div>
    );
}

function ActionNode({ data, selected }: NodeProps<FlowNode<FlowNodeData>>) {
    const nodeData = data as FlowNodeData;
    const simulatedStatus = nodeData.simulatedStatus as
        | 'active'
        | 'success'
        | 'failed'
        | 'idle'
        | undefined;

    let borderClass = 'border-zinc-200 dark:border-zinc-800';
    let ringClass = '';
    let statusLabel = null;

    if (simulatedStatus === 'active') {
        borderClass = 'border-amber-500 scale-105';
        ringClass = 'ring-4 ring-amber-500/30 animate-pulse';
        statusLabel = (
            <span className="rounded bg-amber-500/20 px-1.5 py-0.5 text-[10px] font-bold text-amber-600">
                Berjalan...
            </span>
        );
    } else if (simulatedStatus === 'success') {
        borderClass = 'border-emerald-500';
        ringClass = 'ring-4 ring-emerald-500/20';
        statusLabel = (
            <span className="rounded bg-emerald-500/20 px-1.5 py-0.5 text-[10px] font-bold text-emerald-600">
                ✓ Berhasil
            </span>
        );
    } else if (simulatedStatus === 'failed') {
        borderClass = 'border-rose-500';
        ringClass = 'ring-4 ring-rose-500/20';
        statusLabel = (
            <span className="rounded bg-rose-500/20 px-1.5 py-0.5 text-[10px] font-bold text-rose-600">
                ✗ Dilewati / berhenti
            </span>
        );
    } else if (selected) {
        borderClass = 'border-emerald-600';
        ringClass = 'ring-4 ring-emerald-500/10';
    }

    return (
        <div
            className={`w-[260px] rounded-2xl border bg-white shadow-xl transition-all duration-300 dark:bg-zinc-950 ${borderClass} ${ringClass}`}
        >
            <Handle
                className="!h-3 !w-3 !border-2 !border-white !bg-zinc-400"
                position={Position.Left}
                type="target"
            />
            <div
                className={`rounded-t-[14px] px-4 py-3 ${colorClasses[nodeData.color] ?? colorClasses.emerald}`}
            >
                <div className="flex items-center justify-between gap-2">
                    <span className="text-sm font-black">{nodeData.title}</span>
                    {statusLabel}
                </div>
                <div className="mt-0.5 line-clamp-1 text-[11px] font-semibold opacity-85">
                    {nodeData.subtitle}
                </div>
            </div>
            <div className="px-4 py-2.5 text-left text-[11px] font-bold text-zinc-400 dark:text-zinc-500">
                Step {(nodeData.actionIndex ?? 0) + 1}
            </div>
            <Handle
                className="!h-3 !w-3 !border-2 !border-white !bg-emerald-600"
                position={Position.Right}
                type="source"
            />
        </div>
    );
}

const nodeTypes = {
    startNode: StartNode,
    actionNode: ActionNode,
};

export function createAction(type: ActionType, groups: Group[]): Action {
    if (type === 'send_message') {
        return { type, text: 'Hello! How can we help you?' };
    }

    if (type === 'send_email') {
        return {
            type,
            subject: 'New Notification',
            email_to: 'support@example.com',
            text: 'Default email body',
        };
    }

    if (type === 'http_request') {
        return {
            type,
            method: 'POST',
            url: 'https://api.example.com/webhook',
            body: '{\n  "phone": "{{{senderMobile}}}",\n  "message": "{{{senderMessage}}}"\n}',
        };
    }

    if (type === 'lms_action') {
        return {
            type,
            lms_base_url: 'http://lms-pakandi.test',
            lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
            lms_endpoint: 'auto',
        };
    }

    if (type === 'save_response') {
        return { type, response_field: 'notes' };
    }

    if (type === 'delay') {
        return { type, delay_seconds: 5 };
    }

    if (type === 'add_to_group' || type === 'remove_from_group') {
        return { type, group_id: groups[0]?.id };
    }

    if (type === 'google_sheets') {
        return { type, sheet_name: 'Sheet1' };
    }

    if (type === 'assign_agent') {
        return { type, agent_name: 'Support Team' };
    }

    if (type === 'condition') {
        return {
            type,
            condition: 'message contains price',
            conditions: [
                {
                    operator: 'contains',
                    value: 'price',
                },
            ],
            conditions_relation: 'OR',
        };
    }

    return { type };
}

export function actionCatalogItem(type: ActionType): CatalogItem {
    return catalog.find((item) => item.type === type) ?? catalog[0];
}

export function actionSummary(action: Action, groups: Group[]): string {
    if (action.type === 'send_message') {
        const btnCount = action.buttons?.length ?? 0;
        const prefix = btnCount > 0 ? `🔘 [${btnCount} Tombol] ` : '';
        return prefix + (action.text || 'Empty message');
    }

    if (action.type === 'lms_action') {
        const ep = action.lms_endpoint || 'auto';
        const labelMap: Record<string, string> = {
            auto: 'Deteksi Otomatis',
            verify: 'Verifikasi Akun (Kode 6-Digit)',
            summary: 'Ringkasan & Menu Belajar',
            courses: 'Daftar Kelas yang Diikuti',
            select_course: 'Pilih Kelas Belajar',
            outline: 'Silabus Bab & Materi',
            lesson: 'Baca Materi Pelajaran',
            complete_lesson: 'Tandai Materi Selesai',
            quiz: 'Detail & Link Kuis',
            tasks: 'Agenda Belajar & Tugas',
            certificates: 'Sertifikat Kelulusan',
            search: 'Pencarian Materi LMS',
        };
        return `LMS: ${labelMap[ep] ?? ep}`;
    }

    if (action.type === 'http_request') {
        return `${action.method ?? 'POST'} ${action.url || 'URL Webhook'}`;
    }

    if (action.type === 'delay') {
        return `Wait ${action.delay_seconds ?? 0} seconds`;
    }

    if (action.type === 'add_to_group' || action.type === 'remove_from_group') {
        return `${action.type === 'add_to_group' ? 'Add to' : 'Remove from'}: ${groups.find((group) => group.id === Number(action.group_id))?.name ?? 'Select a group'}`;
    }

    if (action.type === 'send_email') {
        return action.subject || 'Email';
    }

    if (action.type === 'save_response') {
        return `Save response to: ${action.response_field ?? 'notes'}`;
    }

    if (action.type === 'google_sheets') {
        return `Save to sheet: ${action.sheet_name || 'Google Sheet'}`;
    }

    if (action.type === 'assign_agent') {
        return `Assign to: ${action.agent_name || 'Agent'}`;
    }

    if (action.type === 'condition') {
        const conds = action.conditions || [];

        if (conds.length > 0) {
            const relText = action.conditions_relation === 'OR' ? 'or' : 'and';

            return (
                `Condition: ` +
                conds
                    .map(
                        (c, index) =>
                            `[${index + 1}] ${c.operator === 'contains' ? 'contains' : c.operator === 'equals' ? 'equals' : c.operator === 'starts_with' ? 'starts with' : 'ends with'}: ${c.value}`,
                    )
                    .join(` ${relText} `)
            );
        }

        return `If matched: ${action.condition || 'New condition'}`;
    }

    return 'Node settings';
}

function buildGraph(
    actions: Action[],
    groups: Group[],
    simulatedStatuses: Record<
        number,
        'active' | 'success' | 'failed' | 'idle'
    > = {},
) {
    const nodes: FlowNode<FlowNodeData>[] = [
        {
            id: 'start',
            type: 'startNode',
            data: {
                title: 'Start',
                subtitle:
                    'Every incoming message enters here to trigger the flow',
                color: 'emerald',
            },
            position: { x: 120, y: 160 },
            draggable: false,
        },
    ];

    const edges: FlowEdge[] = [];

    actions.forEach((action, index) => {
        const item = actionCatalogItem(action.type);
        const nodeId = `action-${index}`;
        const previousNodeId = index === 0 ? 'start' : `action-${index - 1}`;
        const simulatedStatus = simulatedStatuses[index] || 'idle';

        nodes.push({
            id: nodeId,
            type: 'actionNode',
            data: {
                title: item.title,
                subtitle: actionSummary(action, groups),
                color: item.color,
                actionIndex: index,
                simulatedStatus,
            },
            position: { x: 520 + index * 320, y: index % 2 === 0 ? 180 : 360 },
        });

        // Set edge stroke colors dynamically based on execution status
        let edgeColor = '#059669'; // Emerald default

        if (simulatedStatus === 'success') {
            edgeColor = '#10b981'; // Bright emerald green
        } else if (simulatedStatus === 'failed') {
            edgeColor = '#ef4444'; // Rose red
        } else if (simulatedStatus === 'active') {
            edgeColor = '#f59e0b'; // Amber yellow
        }

        edges.push({
            id: `${previousNodeId}-${nodeId}`,
            source: previousNodeId,
            target: nodeId,
            animated: simulatedStatus === 'active',
            markerEnd: {
                type: MarkerType.ArrowClosed,
                width: 18,
                height: 18,
                color: edgeColor,
            },
            style: { stroke: edgeColor, strokeWidth: 2.5 },
        });
    });

    return { nodes, edges };
}

function serializeGraph(
    nodes: FlowNode<FlowNodeData>[],
    edges: FlowEdge[],
): SerializedGraph {
    return {
        nodes: nodes.map((node) => ({
            id: node.id,
            type: node.type,
            position: node.position,
            data: {
                title: String(node.data.title),
                subtitle: String(node.data.subtitle),
                color: String(node.data.color),
                actionIndex:
                    typeof node.data.actionIndex === 'number'
                        ? node.data.actionIndex
                        : null,
            },
        })),
        edges: edges.map((edge) => ({
            id: edge.id,
            source: edge.source,
            target: edge.target,
            type: edge.type,
            animated: edge.animated,
            label: typeof edge.label === 'string' ? edge.label : undefined,
        })),
    };
}

function mergeSavedGraph(
    baseGraph: ReturnType<typeof buildGraph>,
    savedGraph: SerializedGraph | null,
): ReturnType<typeof buildGraph> {
    if (!savedGraph || savedGraph.nodes.length === 0) {
        return baseGraph;
    }

    const savedNodesById = new Map(
        savedGraph.nodes.map((node) => [node.id, node]),
    );
    const nodes = baseGraph.nodes.map((node) => {
        const savedNode = savedNodesById.get(node.id);

        return savedNode ? { ...node, position: savedNode.position } : node;
    });

    const edges =
        savedGraph.edges.length > 0
            ? savedGraph.edges.map((edge) => ({
                  id: edge.id,
                  source: edge.source,
                  target: edge.target,
                  type: edge.type,
                  animated: edge.animated,
                  label: edge.label,
                  markerEnd: {
                      type: MarkerType.ArrowClosed,
                      width: 18,
                      height: 18,
                      color: '#059669',
                  },
                  style: { stroke: '#059669', strokeWidth: 2.5 },
              }))
            : baseGraph.edges;

    return { nodes, edges };
}

export function FlowBuilder({ groups, flow }: FlowBuilderProps) {
    const importInputRef = React.useRef<HTMLInputElement | null>(null);
    const [paletteSearch, setPaletteSearch] = React.useState('');
    const [isSidebarOpen, setIsSidebarOpen] = React.useState(true);
    const [sidebarTab, setSidebarTab] = React.useState<'nodes' | 'templates'>(
        'nodes',
    );
    const [selectedActionIndex, setSelectedActionIndex] = React.useState<
        number | null
    >(flow?.actions.length ? 0 : null);
    const [formData, setFormData] = React.useState<FlowFormData>({
        name: flow?.name ?? '',
        actions: flow?.actions ? [...flow.actions] : [],
        visual_graph: flow?.visual_graph ?? null,
    });
    const [isProcessing, setIsProcessing] = React.useState(false);

    // Simulation states
    const [simulatedNodeStatuses, setSimulatedNodeStatuses] = React.useState<
        Record<number, 'active' | 'success' | 'failed' | 'idle'>
    >({});
    const [isSimulatorOpen, setIsSimulatorOpen] = React.useState(false);
    const [simulatorMessages, setSimulatorMessages] = React.useState<
        Array<{
            sender: 'user' | 'bot' | 'system';
            text: string;
            buttons?: Array<{ id: string; title: string }>;
        }>
    >([
        {
            sender: 'system',
            text: 'Selamat datang di simulator otomasi WhatsApp. Ketik pesan atau klik tombol yang muncul untuk menguji percabangan alur.',
        },
    ]);
    const [simulatorInput, setSimulatorInput] = React.useState('');
    const [isSimulating, setIsSimulating] = React.useState(false);

    const reactFlowInstanceRef = React.useRef<ReactFlowInstance<
        FlowNode<FlowNodeData>,
        FlowEdge
    > | null>(null);
    const reactFlowWrapper = React.useRef<HTMLDivElement>(null);
    const pendingNodePositionsRef = React.useRef<
        Map<string, { x: number; y: number }>
    >(new Map());
    const addedNodeCounterRef = React.useRef(0);

    const setFormDataField = <Key extends keyof FlowFormData>(
        key: Key,
        value: FlowFormData[Key],
    ) => {
        setFormData((current) => ({ ...current, [key]: value }));
    };

    const getCenterFlowPosition = React.useCallback((): {
        x: number;
        y: number;
    } => {
        if (reactFlowInstanceRef.current && reactFlowWrapper.current) {
            const rect = reactFlowWrapper.current.getBoundingClientRect();
            const clientCenter = {
                x: rect.left + rect.width / 2,
                y: rect.top + rect.height / 2,
            };
            const flowPos =
                reactFlowInstanceRef.current.screenToFlowPosition(clientCenter);
            const staggerOffset = (addedNodeCounterRef.current % 5) * 20;
            addedNodeCounterRef.current += 1;

            return {
                x: Math.round(flowPos.x - 130 + staggerOffset),
                y: Math.round(flowPos.y - 60 + staggerOffset),
            };
        }

        return { x: 450, y: 220 };
    }, []);

    const graph = React.useMemo(
        () =>
            mergeSavedGraph(
                buildGraph(formData.actions, groups, simulatedNodeStatuses),
                formData.visual_graph,
            ),
        [
            formData.actions,
            formData.visual_graph,
            groups,
            simulatedNodeStatuses,
        ],
    );
    const [nodes, setNodes, onNodesChange] = useNodesState<
        FlowNode<FlowNodeData>
    >(graph.nodes);
    const [edges, setEdges, onEdgesChange] = useEdgesState<FlowEdge>(
        graph.edges,
    );

    const onConnect = React.useCallback(
        (connection: any) => {
            setEdges((eds) =>
                addEdge(
                    {
                        ...connection,
                        animated: true,
                        markerEnd: {
                            type: MarkerType.ArrowClosed,
                            width: 18,
                            height: 18,
                            color: '#059669',
                        },
                        style: { stroke: '#059669', strokeWidth: 2.5 },
                    },
                    eds,
                ),
            );
        },
        [setEdges],
    );

    React.useEffect(() => {
        setNodes((currentNodes) => {
            return graph.nodes.map((newNode) => {
                const existing = currentNodes.find((n) => n.id === newNode.id);

                if (existing) {
                    return { ...newNode, position: existing.position };
                }

                const pendingPos = pendingNodePositionsRef.current.get(
                    newNode.id,
                );
                if (pendingPos) {
                    pendingNodePositionsRef.current.delete(newNode.id);

                    return { ...newNode, position: pendingPos };
                }

                return newNode;
            });
        });
        setEdges((currentEdges) => {
            // Keep user custom connections if they exist, otherwise use graph default links
            if (currentEdges.length > 0) {
                const nodeIds = new Set(graph.nodes.map((n) => n.id));

                return currentEdges.filter(
                    (edge) =>
                        nodeIds.has(edge.source) && nodeIds.has(edge.target),
                );
            }

            return graph.edges;
        });
    }, [graph, setEdges, setNodes]);

    const filteredCatalog = React.useMemo(() => {
        const search = paletteSearch.trim().toLowerCase();

        if (!search) {
            return catalog;
        }

        return catalog.filter((item) =>
            `${item.title} ${item.description} ${item.category}`
                .toLowerCase()
                .includes(search),
        );
    }, [paletteSearch]);

    const selectedAction =
        selectedActionIndex !== null
            ? (formData.actions[selectedActionIndex] ?? null)
            : null;

    const handleAddAction = (
        type: ActionType,
        customPosition?: { x: number; y: number },
    ) => {
        const nextActions = [...formData.actions, createAction(type, groups)];
        const newIndex = nextActions.length - 1;
        const newNodeId = `action-${newIndex}`;

        const position = customPosition ?? getCenterFlowPosition();
        pendingNodePositionsRef.current.set(newNodeId, position);

        setFormDataField('actions', nextActions);
        setSelectedActionIndex(newIndex);
    };

    const handleUpdateAction = (index: number, fields: Partial<Action>) => {
        const updated = [...formData.actions];
        updated[index] = { ...updated[index], ...fields };
        setFormDataField('actions', updated);
    };

    const handleRemoveAction = (index: number) => {
        const removedNodeId = `action-${index}`;
        const updated = formData.actions.filter(
            (_, actionIndex) => actionIndex !== index,
        );

        setEdges((currentEdges) => {
            return currentEdges
                .filter(
                    (edge) =>
                        edge.source !== removedNodeId &&
                        edge.target !== removedNodeId,
                )
                .map((edge) => {
                    let source = edge.source;
                    let target = edge.target;

                    const sourceMatch = source.match(/^action-(\d+)$/);
                    if (sourceMatch) {
                        const sIndex = parseInt(sourceMatch[1], 10);
                        if (sIndex > index) {
                            source = `action-${sIndex - 1}`;
                        }
                    }

                    const targetMatch = target.match(/^action-(\d+)$/);
                    if (targetMatch) {
                        const tIndex = parseInt(targetMatch[1], 10);
                        if (tIndex > index) {
                            target = `action-${tIndex - 1}`;
                        }
                    }

                    return { ...edge, source, target };
                });
        });

        setNodes((currentNodes) => {
            const filtered = currentNodes.filter((n) => n.id !== removedNodeId);
            return filtered.map((n) => {
                const match = n.id.match(/^action-(\d+)$/);
                if (match) {
                    const aIndex = parseInt(match[1], 10);
                    if (aIndex > index) {
                        return { ...n, id: `action-${aIndex - 1}` };
                    }
                }
                return n;
            });
        });

        setFormDataField('actions', updated);
        setSelectedActionIndex(
            updated.length > 0 ? Math.min(index, updated.length - 1) : null,
        );
    };

    React.useEffect(() => {
        if (selectedActionIndex === null) {
            return;
        }

        const action = formData.actions[selectedActionIndex];

        if (
            !action ||
            action.type !== 'condition' ||
            (action.conditions?.length ?? 0) > 0
        ) {
            return;
        }

        const raw = action.condition || '';
        const regex =
            /^(?:\{\{\{senderMessage\}\}\}|message)\s+(contains|equals|starts_with|ends_with)\s+(.+)$/i;
        const match = raw.match(regex);
        const parsed = match
            ? {
                  operator: match[1].toLowerCase() as
                      | 'contains'
                      | 'equals'
                      | 'starts_with'
                      | 'ends_with',
                  value: match[2].replace(/^['"]|['"]$/g, '').trim(),
              }
            : { operator: 'contains' as const, value: raw };

        setTimeout(() => {
            handleUpdateAction(selectedActionIndex, {
                conditions: [parsed],
                conditions_relation: 'AND',
            });
        }, 0);
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [selectedActionIndex, formData.actions]);

    const makeTemplateGraph = (
        nodePositions: Array<{ x: number; y: number }>,
        edges: Array<{ source: string; target: string; label?: string }>,
    ): SerializedGraph => ({
        nodes: [
            {
                id: 'start',
                type: 'startNode',
                position: { x: 80, y: 280 },
                data: {},
            },
            ...nodePositions.map((position, index) => ({
                id: `action-${index}`,
                type: 'actionNode',
                position,
                data: { actionIndex: index },
            })),
        ],
        edges: edges.map((edge, index) => ({
            id: `${edge.source}-${edge.target}-${index}`,
            source: edge.source,
            target: edge.target,
            animated: true,
            label: edge.label,
        })),
    });

    const startConditionEdges = (
        branches: Array<{ target: number; labels: string[] }>,
    ) => [
        { source: 'start', target: 'action-0' },
        ...branches.flatMap((branch) =>
            branch.labels.map((label) => ({
                source: 'action-0',
                target: `action-${branch.target}`,
                label,
            })),
        ),
    ];

    const premadeTemplates: FlowTemplate[] = [
        {
            name: 'Asisten Belajar Natagara',
            description:
                'Alur lengkap bot WhatsApp LMS Pak Andi: Router Menu bercabang otomatis ke Verifikasi Akun, Daftar Kelas, Silabus Bab, Baca Materi, Selesaikan Materi, Kuis, Tugas, Sertifikat, dan Pencarian.',
            icon: GraduationCap,
            color: 'emerald',
            actions: [
                // action-0: Router Percabangan Kondisi
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'verifikasi' },
                        { operator: 'contains', value: 'kelas' },
                        { operator: 'contains', value: 'kursus' },
                        { operator: 'contains', value: 'silabus' },
                        { operator: 'contains', value: 'bab' },
                        { operator: 'contains', value: 'materi' },
                        { operator: 'contains', value: 'baca' },
                        { operator: 'contains', value: 'selesai' },
                        { operator: 'contains', value: 'kuis' },
                        { operator: 'contains', value: 'quiz' },
                        { operator: 'contains', value: 'tugas' },
                        { operator: 'contains', value: 'agenda' },
                        { operator: 'contains', value: 'sertifikat' },
                        { operator: 'contains', value: 'cari' },
                        { operator: 'contains', value: 'menu' },
                        { operator: 'contains', value: 'halo' },
                    ],
                    conditions_relation: 'OR',
                },
                // action-1: Verifikasi Akun
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'verify',
                },
                // action-2: Daftar Kelas & Progres Belajar
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'courses',
                },
                // action-3: Silabus Bab & Materi Pelajaran
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'outline',
                },
                // action-4: Baca Materi Pelajaran (Format WhatsApp)
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'lesson',
                },
                // action-5: Tandai Selesai & Klaim Poin
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'complete_lesson',
                },
                // action-6: Detail & Link Kuis
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'quiz',
                },
                // action-7: Agenda Belajar & Tugas Pending
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'tasks',
                },
                // action-8: Sertifikat Kelulusan & Unduh PDF
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'certificates',
                },
                // action-9: Pencarian Topik Materi LMS
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'search',
                },
                // action-10: Ringkasan Belajar & Menu Utama
                {
                    type: 'lms_action',
                    lms_base_url: 'http://lms-pakandi.test',
                    lms_api_key: 'e01c7d50ce2fcd0477438918936d5cfc6561a64428230cd3d687908d767f1a33',
                    lms_endpoint: 'summary',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 550 },
                    { x: 920, y: 50 },
                    { x: 920, y: 160 },
                    { x: 920, y: 270 },
                    { x: 920, y: 380 },
                    { x: 920, y: 490 },
                    { x: 920, y: 600 },
                    { x: 920, y: 710 },
                    { x: 920, y: 820 },
                    { x: 920, y: 930 },
                    { x: 920, y: 1040 },
                ],
                startConditionEdges([
                    { target: 1, labels: ['1', 'verifikasi'] },
                    { target: 2, labels: ['2', 'kelas', 'kursus'] },
                    { target: 3, labels: ['3', 'silabus', 'bab'] },
                    { target: 4, labels: ['4', 'materi', 'baca'] },
                    { target: 5, labels: ['selesai'] },
                    { target: 6, labels: ['5', 'kuis', 'quiz'] },
                    { target: 7, labels: ['6', 'tugas', 'agenda'] },
                    { target: 8, labels: ['7', 'sertifikat'] },
                    { target: 9, labels: ['8', 'cari'] },
                    { target: 10, labels: ['menu', 'info', 'halo'] },
                ]),
            ),
        },
        {
            name: 'Router FAQ Pintar',
            description:
                'Menu FAQ bercabang otomatis di mana setiap pilihan mengarahkan ke balasan pesan tersendiri.',
            icon: MessageSquare,
            color: 'emerald',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: '1' },
                        { operator: 'contains', value: 'harga' },
                        { operator: 'contains', value: 'paket' },
                        { operator: 'contains', value: '2' },
                        { operator: 'contains', value: 'jam' },
                        { operator: 'contains', value: 'jadwal' },
                        { operator: 'contains', value: '3' },
                        { operator: 'contains', value: 'konsultan' },
                        { operator: 'contains', value: 'cs' },
                        { operator: 'contains', value: 'menu' },
                        { operator: 'contains', value: 'halo' },
                        { operator: 'contains', value: 'hai' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Daftar harga dan paket langganan:\n• Starter: Rp 290.000/bulan — 1.000 pesan\n• Pro: Rp 790.000/bulan — 10.000 pesan\n• Enterprise: Rp 1.990.000/bulan — tanpa batas kuota\n\nKetik "langganan" jika Anda berminat untuk memulai.',
                },
                {
                    type: 'send_message',
                    text: 'Jam operasional layanan:\nSenin s/d Jumat\n08.00 - 17.00 WIB\n\nDi luar jam operasional, silakan tinggalkan pesan dan tim kami akan segera menghubungi Anda kembali.',
                },
                {
                    type: 'send_message',
                    text: 'Permintaan Anda untuk berbicara dengan konsultan telah kami terima. Silakan tuliskan pertanyaan atau nomor kontak Anda, tim kami akan segera menghubungi Anda.',
                },
                {
                    type: 'send_message',
                    text: 'Halo kak {{{senderName}}}, ada yang bisa kami bantu? Silakan pilih menu:\n\n1 - Harga dan Paket\n2 - Jam Operasional\n3 - Bicara dengan Konsultan / CS\n\nAnda dapat membalas dengan angka pilihan atau kata kunci yang diinginkan.',
                },
                { type: 'save_response', response_field: 'notes' },
                {
                    type: 'send_email',
                    subject: 'Permintaan alur FAQ',
                    email_to: 'sales@example.com',
                    text: 'Pelanggan {{{senderName}}} ({{{senderMobile}}}) menggunakan alur FAQ.\nPesan: {{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 280 },
                    { x: 860, y: 80 },
                    { x: 860, y: 280 },
                    { x: 860, y: 480 },
                    { x: 860, y: 680 },
                    { x: 1260, y: 480 },
                    { x: 1640, y: 480 },
                ],
                [
                    ...startConditionEdges([
                        { target: 1, labels: ['1', 'harga', 'paket'] },
                        { target: 2, labels: ['2', 'jam', 'jadwal'] },
                        { target: 3, labels: ['3', 'konsultan', 'cs'] },
                        { target: 4, labels: ['menu', 'halo', 'hai'] },
                    ]),
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                ],
            ),
        },
        {
            name: 'Kualifikasi Prospek (Leads)',
            description:
                'Arahkan prospek berdasarkan kebutuhan: penawaran, demo, atau tim sales, lalu simpan datanya.',
            icon: Table2,
            color: 'green',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'penawaran' },
                        { operator: 'contains', value: 'harga' },
                        { operator: 'contains', value: 'demo' },
                        { operator: 'contains', value: 'uji coba' },
                        { operator: 'contains', value: 'sales' },
                        { operator: 'contains', value: 'telepon' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Terima kasih kak {{{senderName}}}. Silakan kirim perkiraan volume pesan per bulan dan nama bisnis Anda agar kami dapat menyiapkan penawaran yang sesuai.',
                },
                {
                    type: 'send_message',
                    text: 'Bagus sekali! Untuk penjadwalan demo produk, mohon kirimkan email Anda dan waktu luang yang diinginkan. Tautan meeting demo akan kami kirimkan.',
                },
                {
                    type: 'send_message',
                    text: 'Permintaan Anda telah diteruskan ke tim sales. Silakan kirimkan pertanyaan atau nomor kontak aktif Anda.',
                },
                {
                    type: 'send_message',
                    text: 'Silakan pilih salah satu opsi kebutuhan Anda:\n- Penawaran\n- Demo\n- Sales',
                },
                { type: 'save_response', response_field: 'notes' },
                {
                    type: 'http_request',
                    method: 'POST',
                    url: 'https://api.example.com/leads',
                    body: '{\n  "name": "{{{senderName}}}",\n  "phone": "{{{senderMobile}}}",\n  "message": "{{{senderMessage}}}",\n  "source": "whatsapp_bot"\n}',
                },
                { type: 'google_sheets', sheet_name: 'Qualified Leads' },
                {
                    type: 'send_email',
                    subject: 'Prospek terualifikasi baru',
                    email_to: 'sales@example.com',
                    text: 'Prospek terualifikasi baru:\n{{{senderName}}} - {{{senderMobile}}}\nPesan: {{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 260 },
                    { x: 860, y: 440 },
                    { x: 860, y: 620 },
                    { x: 1260, y: 360 },
                    { x: 1640, y: 360 },
                    { x: 2020, y: 360 },
                    { x: 2400, y: 360 },
                ],
                [
                    ...startConditionEdges([
                        { target: 1, labels: ['penawaran', 'harga'] },
                        { target: 2, labels: ['demo', 'uji coba'] },
                        { target: 3, labels: ['sales', 'telepon'] },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                    { source: 'action-6', target: 'action-7' },
                    { source: 'action-7', target: 'action-8' },
                ],
            ),
        },
        {
            name: 'Pengarah Ulasan & Masukan',
            description:
                'Pilah ulasan positif, keluhan, dan masukan netral secara otomatis sambil mencatat dan memberi tahu tim.',
            icon: Users,
            color: 'sky',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: '5' },
                        { operator: 'contains', value: 'sangat bagus' },
                        { operator: 'contains', value: '4' },
                        { operator: 'contains', value: 'puas' },
                        { operator: 'contains', value: '1' },
                        { operator: 'contains', value: 'kecewa' },
                        { operator: 'contains', value: 'kendala' },
                        { operator: 'contains', value: '2' },
                        { operator: 'contains', value: '3' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Terima kasih banyak atas penilaian terbaiknya, kak {{{senderName}}}! Senang bisa memberikan pengalaman berbelanja yang memuaskan.',
                },
                {
                    type: 'send_message',
                    text: 'Kami memohon maaf yang sebesar-besarnya atas ketidaknyamanan yang dialami. Masukan Anda telah kami tandai sebagai prioritas utama dan tim penjamin kualitas kami akan segera menindaklanjuti.',
                },
                {
                    type: 'send_message',
                    text: 'Terima kasih atas saran dan masukan Anda. Catatan ini akan kami pelajari untuk meningkatkan mutu layanan kami. Anda bisa mengirimkan detail tambahan di sini.',
                },
                {
                    type: 'send_message',
                    text: 'Kirimkan penilaian Anda berupa angka atau kata kunci:\n5 (Sangat Bagus)\n4 (Puas)\n1 (Kecewa/Kendala)\n2 atau 3 (Cukup / Netral)',
                },
                { type: 'save_response', response_field: 'var1' },
                { type: 'google_sheets', sheet_name: 'Customer Feedback' },
                {
                    type: 'send_email',
                    subject: 'Ulasan dan masukan pelanggan baru',
                    email_to: 'feedback@example.com',
                    text: 'Masukan baru dari {{{senderName}}} ({{{senderMobile}}}):\n{{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 300 },
                    { x: 860, y: 520 },
                    { x: 860, y: 720 },
                    { x: 1260, y: 300 },
                    { x: 1640, y: 300 },
                    { x: 2020, y: 300 },
                ],
                [
                    ...startConditionEdges([
                        { target: 1, labels: ['5', 'sangat bagus', '4', 'puas'] },
                        { target: 2, labels: ['1', 'kecewa', 'kendala'] },
                        { target: 3, labels: ['2', '3'] },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                    { source: 'action-6', target: 'action-7' },
                ],
            ),
        },
        {
            name: 'Pengalihan ke Agen CS (Manusia)',
            description:
                'Klasifikasikan kendala mendesak, pembayaran/tagihan, dan bantuan umum sebelum dialihkan ke tim agen yang tepat.',
            icon: UserRoundCog,
            color: 'rose',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'darurat' },
                        { operator: 'contains', value: 'error' },
                        { operator: 'contains', value: 'rusak' },
                        { operator: 'contains', value: 'tagihan' },
                        { operator: 'contains', value: 'pembayaran' },
                        { operator: 'contains', value: 'langganan' },
                        { operator: 'contains', value: 'bantuan' },
                        { operator: 'contains', value: 'cs' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Laporan Anda telah ditandai sebagai DARURAT / MENDESAK. Mohon kirimkan kronologi singkat serta tangkapan layar jika ada. Permintaan Anda sedang kami teruskan ke teknisi siaga.',
                },
                {
                    type: 'send_message',
                    text: 'Pertanyaan Anda telah diteruskan ke bagian keuangan & penagihan. Silakan kirim nomor faktur atau email terdaftar Anda agar kami dapat melakukan pengecekan.',
                },
                {
                    type: 'send_message',
                    text: 'Permintaan bantuan Anda telah kami terima. Silakan jelaskan rincian kebutuhan Anda, petugas Customer Service kami akan segera merespons.',
                },
                {
                    type: 'send_message',
                    text: 'Pilih jenis bantuan yang Anda perlukan:\nDarurat (Sistem Error)\nTagihan (Pembayaran)\nBantuan (Pertanyaan Umum)',
                },
                { type: 'save_response', response_field: 'var2' },
                { type: 'assign_agent', agent_name: 'Antrean Support' },
                { type: 'disable_autoreply' },
                {
                    type: 'send_email',
                    subject: 'Permintaan bantuan perlu tindak lanjut agen',
                    email_to: 'support@example.com',
                    text: 'Permintaan bantuan dari {{{senderName}}} ({{{senderMobile}}}):\n{{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 300 },
                    { x: 860, y: 520 },
                    { x: 860, y: 720 },
                    { x: 1260, y: 300 },
                    { x: 1640, y: 300 },
                    { x: 2020, y: 300 },
                    { x: 2400, y: 300 },
                ],
                [
                    ...startConditionEdges([
                        {
                            target: 1,
                            labels: ['darurat', 'error', 'rusak'],
                        },
                        {
                            target: 2,
                            labels: ['tagihan', 'pembayaran', 'langganan'],
                        },
                        { target: 3, labels: ['bantuan', 'cs'] },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                    { source: 'action-6', target: 'action-7' },
                    { source: 'action-7', target: 'action-8' },
                ],
            ),
        },
        {
            name: 'Pelacakan Pesanan & Purna Jual',
            description:
                'Arahkan pertanyaan nomor resi, pengembalian barang, dan pesanan terlambat, lalu catat datanya secara rapi.',
            icon: Globe2,
            color: 'purple',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'resi' },
                        { operator: 'contains', value: 'lacak' },
                        { operator: 'contains', value: '#' },
                        { operator: 'contains', value: 'retur' },
                        { operator: 'contains', value: 'kembali' },
                        { operator: 'contains', value: 'terlambat' },
                        { operator: 'contains', value: 'belum sampai' },
                        { operator: 'contains', value: 'lama' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Silakan kirimkan nomor pesanan atau nomor resi pengiriman Anda, kami akan segera melacak status paket terkini.',
                },
                {
                    type: 'send_message',
                    text: 'Untuk proses retur atau penukaran barang, mohon sertakan nomor pesanan dan alasan pengembalian. Kami akan mengirimkan petunjuk retur lengkap.',
                },
                {
                    type: 'send_message',
                    text: 'Mohon maaf atas keterlambatan paket Anda. Silakan ketik nomor pesanan Anda, kami akan segera berkoordinasi dengan bagian ekspedisi.',
                },
                {
                    type: 'send_message',
                    text: 'Pilih jenis bantuan pesanan:\nLacak (Cek Resi)\nRetur (Pengembalian Barang)\nTerlambat (Paket Belum Sampai)',
                },
                { type: 'save_response', response_field: 'var3' },
                {
                    type: 'http_request',
                    method: 'POST',
                    url: 'https://api.example.com/orders/track',
                    body: '{\n  "phone": "{{{senderMobile}}}",\n  "query": "{{{senderMessage}}}",\n  "customer": "{{{senderName}}}"\n}',
                },
                { type: 'google_sheets', sheet_name: 'Order Inquiries' },
                {
                    type: 'send_email',
                    subject: 'Pertanyaan status pesanan baru',
                    email_to: 'operations@example.com',
                    text: 'Pertanyaan pesanan dari {{{senderName}}}:\n{{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 300 },
                    { x: 860, y: 520 },
                    { x: 860, y: 720 },
                    { x: 1260, y: 300 },
                    { x: 1640, y: 300 },
                    { x: 2020, y: 300 },
                    { x: 2400, y: 300 },
                ],
                [
                    ...startConditionEdges([
                        { target: 1, labels: ['resi', 'lacak', '#'] },
                        { target: 2, labels: ['retur', 'kembali'] },
                        {
                            target: 3,
                            labels: ['terlambat', 'belum sampai', 'lama'],
                        },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                    { source: 'action-6', target: 'action-7' },
                    { source: 'action-7', target: 'action-8' },
                ],
            ),
        },
        {
            name: 'Orientasi & Aktivasi Pelanggan Baru',
            description:
                'Pandu pelanggan baru mulai dari panduan cepat, aktivasi akun, hingga bantuan teknis sambil menyimpannya ke CRM.',
            icon: Mail,
            color: 'violet',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'panduan' },
                        { operator: 'contains', value: 'mulai' },
                        { operator: 'contains', value: 'aktivasi' },
                        { operator: 'contains', value: 'akun' },
                        { operator: 'contains', value: 'bantuan' },
                        { operator: 'contains', value: 'kendala' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Selamat datang kak {{{senderName}}}! Panduan cepat: hubungkan perangkat Anda, impor kontak, lalu kirim pesan uji coba pertama Anda.',
                },
                {
                    type: 'send_message',
                    text: 'Untuk aktivasi akun, silakan kirimkan email terdaftar serta nama usaha/instansi Anda. Kami akan segera memverifikasi status aktivasi.',
                },
                {
                    type: 'send_message',
                    text: 'Anda telah terhubung dengan tim pendampingan teknis. Ceritakan di bagian mana Anda mengalami kendala atau pesan kesalahan apa yang muncul.',
                },
                {
                    type: 'send_message',
                    text: 'Pilih panduan yang Anda butuhkan:\nPanduan (Mulai Cepat)\nAktivasi (Aktivasi Akun)\nBantuan (Kendala Teknis)',
                },
                { type: 'add_to_group', group_id: groups[0]?.id },
                { type: 'save_response', response_field: 'notes' },
                { type: 'google_sheets', sheet_name: 'New Customers' },
                {
                    type: 'http_request',
                    method: 'POST',
                    url: 'https://api.example.com/crm/contacts',
                    body: '{\n  "name": "{{{senderName}}}",\n  "phone": "{{{senderMobile}}}",\n  "tag": "vip",\n  "source": "whatsapp"\n}',
                },
                {
                    type: 'send_email',
                    subject: 'Pelanggan baru memerlukan aktivasi',
                    email_to: 'success@example.com',
                    text: 'Pelanggan baru:\n{{{senderName}}} - {{{senderMobile}}}\n{{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 300 },
                    { x: 860, y: 520 },
                    { x: 860, y: 720 },
                    { x: 1260, y: 300 },
                    { x: 1640, y: 300 },
                    { x: 2020, y: 300 },
                    { x: 2400, y: 300 },
                    { x: 2780, y: 300 },
                ],
                [
                    ...startConditionEdges([
                        { target: 1, labels: ['panduan', 'mulai'] },
                        { target: 2, labels: ['aktivasi', 'akun'] },
                        { target: 3, labels: ['bantuan', 'kendala'] },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                    { source: 'action-6', target: 'action-7' },
                    { source: 'action-7', target: 'action-8' },
                    { source: 'action-8', target: 'action-9' },
                ],
            ),
        },
        {
            name: 'Reservasi & Janji Temu Pintar',
            description:
                'Kelola pendaftaran janji temu baru, ubah jadwal, dan pembatalan secara otomatis, lalu catat ke tim Anda.',
            icon: Clock3,
            color: 'orange',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'daftar' },
                        { operator: 'contains', value: 'janji temu' },
                        { operator: 'contains', value: 'booking' },
                        { operator: 'contains', value: 'ubah jadwal' },
                        { operator: 'contains', value: 'ganti' },
                        { operator: 'contains', value: 'batal' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Untuk membuat janji temu baru, silakan kirim nama lengkap Anda, layanan yang diinginkan, serta hari/jam yang Anda kehendaki.',
                },
                {
                    type: 'send_message',
                    text: 'Untuk mengubah jadwal, mohon kirimkan nomor tiket booking Anda serta pilihan jadwal baru yang diinginkan.',
                },
                {
                    type: 'send_message',
                    text: 'Untuk pembatalan janji temu, mohon kirimkan nomor tiket booking atau nomor telepon yang digunakan saat reservasi.',
                },
                {
                    type: 'send_message',
                    text: 'Pilih menu reservasi:\nDaftar (Janji Temu Baru)\nUbah Jadwal (Reschedule)\nBatal (Pembatalan Reservasi)',
                },
                { type: 'save_response', response_field: 'notes' },
                { type: 'google_sheets', sheet_name: 'Appointment Requests' },
                {
                    type: 'send_email',
                    subject: 'Permintaan janji temu WhatsApp',
                    email_to: 'booking@example.com',
                    text: 'Permintaan janji temu dari {{{senderName}}} ({{{senderMobile}}}):\n{{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 300 },
                    { x: 860, y: 520 },
                    { x: 860, y: 720 },
                    { x: 1260, y: 300 },
                    { x: 1640, y: 300 },
                    { x: 2020, y: 300 },
                ],
                [
                    ...startConditionEdges([
                        {
                            target: 1,
                            labels: ['daftar', 'janji temu', 'booking'],
                        },
                        { target: 2, labels: ['ubah jadwal', 'ganti'] },
                        { target: 3, labels: ['batal'] },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                    { source: 'action-6', target: 'action-7' },
                ],
            ),
        },
        {
            name: 'Keranjang Tertinggal & Penawaran Toko',
            description:
                'Tindak lanjuti pesanan yang belum selesai, voucher diskon, dan tanya ketersediaan produk ke calon pembeli.',
            icon: Sparkles,
            color: 'amber',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'keranjang' },
                        { operator: 'contains', value: 'checkout' },
                        { operator: 'contains', value: 'diskon' },
                        { operator: 'contains', value: 'promo' },
                        { operator: 'contains', value: 'produk' },
                        { operator: 'contains', value: 'stok' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Kami melihat Anda belum menyelesaikan pesanan Anda. Kirimkan tautan keranjang atau nama produk dan kami siap membantu menyelesaikan checkout Anda.',
                },
                {
                    type: 'send_message',
                    text: 'Untuk mendapatkan kode promo/diskon khusus, kirimkan nama produk atau kategori yang Anda minati. Kami akan bagikan penawaran terbaik hari ini.',
                },
                {
                    type: 'send_message',
                    text: 'Silakan tanyakan nama produk atau kirimkan foto/link produk yang Anda cari. Kami akan segera memeriksa ketersediaan stok dan harganya.',
                },
                {
                    type: 'send_message',
                    text: 'Pilih bantuan belanja:\nKeranjang (Lanjut Checkout)\nDiskon (Klaim Promo)\nProduk (Cek Stok & Harga)',
                },
                { type: 'save_response', response_field: 'var4' },
                {
                    type: 'http_request',
                    method: 'POST',
                    url: 'https://api.example.com/shop/lead',
                    body: '{\n  "phone": "{{{senderMobile}}}",\n  "name": "{{{senderName}}}",\n  "message": "{{{senderMessage}}}"\n}',
                },
                {
                    type: 'send_email',
                    subject: 'Peluang penjualan WhatsApp baru',
                    email_to: 'store@example.com',
                    text: 'Peluang penjualan:\n{{{senderName}}} - {{{senderMobile}}}\n{{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 300 },
                    { x: 860, y: 520 },
                    { x: 860, y: 720 },
                    { x: 1260, y: 300 },
                    { x: 1640, y: 300 },
                    { x: 2020, y: 300 },
                ],
                [
                    ...startConditionEdges([
                        { target: 1, labels: ['keranjang', 'checkout'] },
                        { target: 2, labels: ['diskon', 'promo'] },
                        { target: 3, labels: ['produk', 'stok'] },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                    { source: 'action-6', target: 'action-7' },
                ],
            ),
        },
        {
            name: 'Perpanjangan Langganan & Tagihan',
            description:
                'Tangani permohonan perpanjangan paket, konfirmasi pembayaran, dan kendala invoice sebelum diteruskan ke bagian keuangan.',
            icon: BellOff,
            color: 'rose',
            actions: [
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'perpanjang' },
                        { operator: 'contains', value: 'langganan' },
                        { operator: 'contains', value: 'pembayaran' },
                        { operator: 'contains', value: 'bayar' },
                        { operator: 'contains', value: 'invoice' },
                        { operator: 'contains', value: 'tagihan' },
                        { operator: 'contains', value: 'menu' },
                    ],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Untuk memperpanjang langganan Anda, silakan kirimkan email akun terdaftar dan nama paket yang diinginkan. Kami akan kirimkan tautan pembayaran resmi.',
                },
                {
                    type: 'send_message',
                    text: 'Untuk konfirmasi atau pengecekan pembayaran, kirimkan nomor invoice atau bukti transfer Anda agar tim kami segera memverifikasi.',
                },
                {
                    type: 'send_message',
                    text: 'Jika ada kendala pada tagihan atau invoice, mohon kirimkan nomor invoice dan uraian kendala yang dialami.',
                },
                {
                    type: 'send_message',
                    text: 'Pilih jenis layanan:\nPerpanjang (Perpanjang Paket)\nPembayaran (Konfirmasi Transfer)\nInvoice (Kendala Tagihan)',
                },
                { type: 'save_response', response_field: 'var5' },
                {
                    type: 'send_email',
                    subject: 'Permintaan perpanjangan atau tagihan baru',
                    email_to: 'billing@example.com',
                    text: 'Permintaan tagihan/perpanjangan:\n{{{senderName}}} - {{{senderMobile}}}\n{{{senderMessage}}}',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 300 },
                    { x: 860, y: 80 },
                    { x: 860, y: 300 },
                    { x: 860, y: 520 },
                    { x: 860, y: 720 },
                    { x: 1260, y: 300 },
                    { x: 1640, y: 300 },
                ],
                [
                    ...startConditionEdges([
                        { target: 1, labels: ['perpanjang', 'langganan'] },
                        { target: 2, labels: ['pembayaran', 'bayar'] },
                        { target: 3, labels: ['invoice', 'tagihan'] },
                        { target: 4, labels: ['menu'] },
                    ]),
                    { source: 'action-1', target: 'action-5' },
                    { source: 'action-2', target: 'action-5' },
                    { source: 'action-3', target: 'action-5' },
                    { source: 'action-5', target: 'action-6' },
                ],
            ),
        },
        {
            name: 'Bot All-in-One: Customer Service & LMS Belajar (Tombol)',
            description:
                'Alur lengkap terpadu (CS + LMS) berbasis TOMBOL interaktif. Menghindari balasan ganda. Menu utama membagi 2 cabang: Layanan CS dan Belajar LMS.',
            icon: Sparkles,
            color: 'emerald',
            actions: [
                // action-0: Master Router — menangkap klik tombol maupun teks user
                {
                    type: 'condition',
                    conditions: [
                        { operator: 'contains', value: 'halo' },        // 0 → Menu Utama
                        { operator: 'contains', value: 'hai' },         // 1 → Menu Utama
                        { operator: 'contains', value: 'menu' },        // 2 → Menu Utama
                        { operator: 'contains', value: 'mulai' },       // 3 → Menu Utama
                        { operator: 'contains', value: 'cs' },          // 4 → Sub-menu CS (Tombol '🎧 Layanan CS')
                        { operator: 'contains', value: 'layanan' },     // 5 → Sub-menu CS
                        { operator: 'contains', value: 'bantuan' },     // 6 → Sub-menu CS
                        { operator: 'contains', value: 'info' },        // 7 → Info Layanan (Tombol '📋 Info Layanan')
                        { operator: 'contains', value: 'harga' },       // 8 → Detail Harga (Tombol '💰 Harga & Paket')
                        { operator: 'contains', value: 'paket' },       // 9 → Detail Harga
                        { operator: 'contains', value: 'produk' },      // 10 → Detail Produk (Tombol '🛍️ Produk Kami')
                        { operator: 'contains', value: 'jam' },         // 11 → Jam & Lokasi (Tombol '🕐 Jam & Lokasi')
                        { operator: 'contains', value: 'lokasi' },      // 12 → Jam & Lokasi
                        { operator: 'contains', value: 'alamat' },      // 13 → Jam & Lokasi
                        { operator: 'contains', value: 'agen' },        // 14 → Hubungi Agen CS (Tombol '🎧 Hubungi Agen CS')
                        { operator: 'contains', value: 'operator' },    // 15 → Hubungi Agen CS
                        { operator: 'contains', value: 'bicara' },      // 16 → Hubungi Agen CS
                        { operator: 'contains', value: 'hubungi' },     // 17 → Hubungi Agen CS
                        { operator: 'contains', value: 'lms' },         // 18 → Sub-menu LMS (Tombol '📚 Belajar LMS')
                        { operator: 'contains', value: 'belajar' },     // 19 → Sub-menu LMS
                        { operator: 'contains', value: 'kelas' },       // 20 → Daftar Kelas (Tombol '📚 Daftar Kelas')
                        { operator: 'contains', value: 'kursus' },      // 21 → Daftar Kelas
                        { operator: 'contains', value: 'materi' },      // 22 → Baca Materi (Tombol '📖 Baca Materi')
                        { operator: 'contains', value: 'baca' },        // 23 → Baca Materi
                        { operator: 'contains', value: 'silabus' },     // 24 → Baca Materi
                        { operator: 'contains', value: 'tugas' },       // 25 → Tugas (Tombol '📝 Cek Tugas')
                        { operator: 'contains', value: 'pr' },          // 26 → Tugas
                        { operator: 'contains', value: 'ujian' },       // 27 → Ujian & Kuis (Tombol '📋 Ujian & Kuis')
                        { operator: 'contains', value: 'quiz' },        // 28 → Ujian & Kuis
                        { operator: 'contains', value: 'kuis' },        // 29 → Ujian & Kuis
                        { operator: 'contains', value: 'sertifikat' },  // 30 → Sertifikat (Tombol '🏆 Cek Sertifikat')
                        { operator: 'contains', value: 'verifikasi' },  // 31 → Verifikasi Akun LMS
                        { operator: 'contains', value: 'verif' },       // 32 → Verifikasi Akun LMS
                        { operator: 'contains', value: 'kode' },        // 33 → Verifikasi Akun LMS
                        { operator: 'contains', value: 'list kelas' },  // 34 → Daftar Kelas
                        { operator: 'contains', value: 'daftar kelas' },// 35 → Daftar Kelas
                        { operator: 'contains', value: 'kelas 1' },     // 36 → Pilih Kelas 1
                        { operator: 'contains', value: 'kelas 2' },     // 37 → Pilih Kelas 2
                        { operator: 'contains', value: 'kelas 3' },     // 38 → Pilih Kelas 3
                        { operator: 'contains', value: 'selesai' },     // 39 → Selesai Baca Materi
                        { operator: 'contains', value: 'materi selanjutnya' }, // 40 → Materi Selanjutnya
                        { operator: 'contains', value: 'selesai baca' }, // 41 → Selesai Baca
                    ],
                    conditions_relation: 'OR',
                },
                // action-1: Sambutan & Menu Utama (DENGAN 2 TOMBOL BESAR)
                {
                    type: 'send_message',
                    text: 'Halo kak {{{senderName}}} 👋\n\nSelamat datang di Layanan Terpadu Natagara! Kami siap membantu Anda.\n\nSilakan pilih layanan yang Anda butuhkan:',
                    buttons: ['Layanan CS', 'Belajar LMS'],
                    footer_text: 'Tap tombol untuk memilih',
                },

                // ─── CABANG 1: CUSTOMER SERVICE ───────────────────────
                // action-2: Sub-Menu CS
                {
                    type: 'send_message',
                    text: '🎧 *Layanan Pelanggan (Customer Service)*\n\nSilakan pilih opsi bantuan di bawah ini:',
                    buttons: ['Info Layanan', 'Hubungi Agen CS', 'Menu Utama'],
                    footer_text: 'Pilih layanan CS',
                },
                // action-3: Sub-Menu Info Layanan
                {
                    type: 'send_message',
                    text: '📋 *Informasi Produk & Operasional*\n\nPilih informasi yang ingin Anda ketahui:',
                    buttons: ['Harga & Paket', 'Produk Kami', 'Jam & Lokasi'],
                    footer_text: 'Pilih kategori informasi',
                },
                // action-4: Detail Harga & Paket
                {
                    type: 'send_message',
                    text: '💰 *Daftar Harga & Paket*\n\n━━━━━━━━━━━━━━━━━━━━\n🥉 *Paket Starter* — Rp 290.000/bln\n✅ 1.000 pesan/bulan • 1 nomor WA\n\n🥈 *Paket Pro* — Rp 790.000/bln\n✅ 10.000 pesan/bulan • 3 nomor WA\n✅ Support prioritas & analitik\n\n🥇 *Paket Enterprise* — Rp 1.990.000/bln\n✅ Kuota pesan & nomor tanpa batas\n✅ Dedicated support & integrasi API\n━━━━━━━━━━━━━━━━━━━━',
                    buttons: ['Hubungi Agen CS', 'Produk Kami', 'Menu Utama'],
                    footer_text: 'Pilih langkah selanjutnya',
                },
                // action-5: Detail Produk & Layanan
                {
                    type: 'send_message',
                    text: '🛍️ *Produk & Layanan Kami*\n\n━━━━━━━━━━━━━━━━━━━━\n📱 *WhatsApp Automation*\nKirim pesan otomatis, balas cerdas & tombol interaktif.\n\n📣 *Campaign Massal*\nKirim broadcast template resmi ke ribuan kontak.\n\n📊 *Live Analytics*\nPantau pesan terkirim, dibaca, dan konversi real-time.\n\n🔗 *Integrasi API & Webhook*\nHubungkan WhatsApp ke website, CRM, atau sistem kasir.\n━━━━━━━━━━━━━━━━━━━━',
                    buttons: ['Harga & Paket', 'Hubungi Agen CS', 'Menu Utama'],
                    footer_text: 'Pilih langkah selanjutnya',
                },
                // action-6: Detail Jam Operasional & Lokasi
                {
                    type: 'send_message',
                    text: '🕐 *Jam Operasional & Kantor*\n\n━━━━━━━━━━━━━━━━━━━━\n⏰ *Senin — Jumat*: 08.00 — 17.00 WIB\n⏰ *Sabtu*: 09.00 — 14.00 WIB\n❌ *Minggu & Libur Nasional*: Tutup\n\n🏢 *Kantor Pusat*:\nJl. Natagara Business Park No. 88\nJakarta Selatan 12340\n\n📞 *Hotline*: +62 21-1234-5678\n📧 *Email*: hello@natagara.com\n━━━━━━━━━━━━━━━━━━━━',
                    buttons: ['Hubungi Agen CS', 'Harga & Paket', 'Menu Utama'],
                    footer_text: 'Pilih langkah selanjutnya',
                },
                // action-7: Simpan Respons Info
                { type: 'save_response', response_field: 'notes' },
                // action-8: Konfirmasi Pengalihan ke Agen CS
                {
                    type: 'send_message',
                    text: '🎧 *Menghubungkan Anda dengan Agen CS*\n\nHalo kak {{{senderName}}}, permintaan Anda telah diteruskan ke tim Customer Service.\n\n⏳ Mohon tunggu sebentar, agen kami akan segera bergabung dalam obrolan ini.\n\n📝 *Silakan ketik kendala atau pertanyaan Anda di bawah:*',
                    footer_text: 'Tim CS kami segera merespons',
                },
                // action-9: Simpan Pertanyaan CS
                { type: 'save_response', response_field: 'var1' },
                // action-10: Notifikasi Email ke Tim CS
                {
                    type: 'send_email',
                    subject: 'Permintaan CS Baru — Perlu Tindak Lanjut Segera',
                    email_to: 'cs-team@example.com',
                    text: 'Ada pelanggan membutuhkan bantuan agen CS:\n\nNama: {{{senderName}}}\nNomor: {{{senderMobile}}}\nPesan: {{{senderMessage}}}\n\nMohon segera tangani pelanggan ini.',
                },
                // action-11: Tugaskan ke Agen CS
                { type: 'assign_agent', agent_name: 'Tim Customer Service' },
                // action-12: Matikan Balas Otomatis Bot
                { type: 'disable_autoreply' },

                // ─── CABANG 2: LMS BELAJAR ────────────────────────────
                // action-13: Sub-Menu LMS
                {
                    type: 'send_message',
                    text: '📚 *Portal Belajar LMS Natagara*\n\nHalo kak {{{senderName}}} 👋\nSilakan pilih aktivitas pembelajaran Anda di bawah ini:\n\n💡 *Tips:* Untuk menghubungkan akun baru dari web LMS, cukup kirimkan: *verifikasi [kode]* (contoh: *verifikasi 120947*).',
                    buttons: ['Daftar Kelas', 'Baca Materi', 'Ujian & Kuis'],
                    footer_text: 'Pilih menu belajar',
                },
                // action-14: Verifikasi Akun LMS
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'verify',
                },
                // action-15: Ringkasan Belajar
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'summary',
                },
                // action-16: Daftar Kelas yang Diikuti
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'courses',
                },
                // action-17: Pilih Kelas Belajar
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'select_course',
                },
                // action-18: Silabus / Outline Kelas
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'outline',
                },
                // action-19: Baca Materi Pelajaran
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'lesson',
                },
                // action-20: Tandai Selesai & Klaim Poin
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'complete_lesson',
                },
                // action-21: Navigasi Setelah Baca Materi (DENGAN TOMBOL)
                {
                    type: 'send_message',
                    text: '✅ *Materi Selesai Dipelajari!*\n\nPoin progres telah dicatat. Silakan pilih langkah selanjutnya:',
                    buttons: ['Cek Tugas', 'Ujian & Kuis', 'List Kelas'],
                    footer_text: 'Lanjut ke tahapan berikutnya',
                },
                // action-22: Daftar Tugas & Agenda Belajar
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'tasks',
                },
                // action-23: Panduan Pengerjaan Tugas (DENGAN TOMBOL)
                {
                    type: 'send_message',
                    text: '📝 *Instruksi Pengumpulan Tugas*\n\n1️⃣ Buka link tugas di atas\n2️⃣ Upload file atau jawaban Anda ke LMS\n3️⃣ Submit sebelum batas waktu berakhir ⏰',
                    buttons: ['Baca Materi', 'Ujian & Kuis', 'List Kelas'],
                    footer_text: 'Pilih menu setelah tugas',
                },
                // action-24: Simpan Konfirmasi Tugas
                { type: 'save_response', response_field: 'var2' },
                // action-25: Detail & Link Ujian / Kuis
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'quiz',
                },
                // action-26: Panduan Sebelum Ujian (DENGAN TOMBOL)
                {
                    type: 'send_message',
                    text: '📋 *Panduan Mengerjakan Ujian*\n\n⏰ Waktu pengerjaan terbatas.\n✍️ Kerjakan dengan teliti dan jujur.\n\nKlik link ujian di atas untuk memulai. Semangat kak {{{senderName}}}! 💪',
                    buttons: ['Baca Materi', 'Cek Tugas', 'List Kelas'],
                    footer_text: 'Pilih menu evaluasi',
                },
                // action-27: Cek Sertifikat Kelulusan
                {
                    type: 'lms_action',
                    lms_base_url: 'https://lms.natagara.com',
                    lms_api_key: '',
                    lms_endpoint: 'certificates',
                },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 560 },   // action-0: Master Router
                    { x: 960, y: 80 },    // action-1: Menu Utama Sambutan (+2 Buttons)
                    // CS Branch
                    { x: 960, y: 320 },   // action-2: Sub-Menu CS (+3 Buttons)
                    { x: 1460, y: 320 },  // action-3: Sub-Menu Info (+3 Buttons)
                    { x: 1960, y: 160 },  // action-4: Detail Harga (+3 Buttons)
                    { x: 1960, y: 320 },  // action-5: Detail Produk (+3 Buttons)
                    { x: 1960, y: 480 },  // action-6: Jam & Lokasi (+3 Buttons)
                    { x: 2460, y: 320 },  // action-7: Simpan Respons Info
                    { x: 1460, y: 640 },  // action-8: Konfirmasi Agen CS
                    { x: 1960, y: 640 },  // action-9: Simpan Pertanyaan CS
                    { x: 2460, y: 640 },  // action-10: Email CS
                    { x: 2960, y: 640 },  // action-11: Tugaskan CS
                    { x: 3460, y: 640 },  // action-12: Nonaktifkan Bot
                    // LMS Branch
                    { x: 960, y: 960 },   // action-13: Sub-Menu LMS (+3 Buttons)
                    { x: 1460, y: 960 },  // action-14: Verify
                    { x: 1960, y: 960 },  // action-15: Summary
                    { x: 2460, y: 960 },  // action-16: Courses
                    { x: 2960, y: 960 },  // action-17: Panduan Kelas (+3 Buttons)
                    { x: 1460, y: 1200 }, // action-18: Outline
                    { x: 1960, y: 1200 }, // action-19: Lesson
                    { x: 2460, y: 1200 }, // action-20: Complete
                    { x: 2960, y: 1200 }, // action-21: Navigasi Materi (+3 Buttons)
                    { x: 1460, y: 1440 }, // action-22: Tasks
                    { x: 1960, y: 1440 }, // action-23: Panduan Tugas (+3 Buttons)
                    { x: 2460, y: 1440 }, // action-24: Save Tugas
                    { x: 1460, y: 1680 }, // action-25: Quiz
                    { x: 1960, y: 1680 }, // action-26: Panduan Ujian (+3 Buttons)
                    { x: 1460, y: 1920 }, // action-27: Sertifikat
                ],
                [
                    { source: 'start', target: 'action-0' },
                    // Master Router branch connections (tanpa emoji di label agar cocok murni)
                    { source: 'action-0', target: 'action-1', label: 'Menu Utama' },
                    { source: 'action-0', target: 'action-2', label: 'Layanan CS' },
                    { source: 'action-0', target: 'action-3', label: 'Info Layanan' },
                    { source: 'action-0', target: 'action-4', label: 'Harga & Paket' },
                    { source: 'action-0', target: 'action-5', label: 'Produk Kami' },
                    { source: 'action-0', target: 'action-6', label: 'Jam & Lokasi' },
                    { source: 'action-0', target: 'action-8', label: 'Hubungi Agen CS' },
                    { source: 'action-0', target: 'action-16', label: 'Belajar LMS' },
                    { source: 'action-0', target: 'action-14', label: 'Verifikasi' },
                    { source: 'action-0', target: 'action-16', label: 'Daftar Kelas' },
                    { source: 'action-0', target: 'action-16', label: 'List Kelas' },
                    { source: 'action-0', target: 'action-17', label: 'Kelas 1' },
                    { source: 'action-0', target: 'action-17', label: 'Kelas 2' },
                    { source: 'action-0', target: 'action-17', label: 'Kelas 3' },
                    { source: 'action-0', target: 'action-19', label: 'Baca Materi' },
                    { source: 'action-0', target: 'action-19', label: 'Materi Selanjutnya' },
                    { source: 'action-0', target: 'action-20', label: 'Selesai Baca' },
                    { source: 'action-0', target: 'action-20', label: 'Selesai' },
                    { source: 'action-0', target: 'action-22', label: 'Cek Tugas' },
                    { source: 'action-0', target: 'action-25', label: 'Ujian & Kuis' },
                    { source: 'action-0', target: 'action-27', label: 'Cek Sertifikat' },
                    // CS connections
                    { source: 'action-4', target: 'action-7' },
                    { source: 'action-5', target: 'action-7' },
                    { source: 'action-6', target: 'action-7' },
                    { source: 'action-8', target: 'action-9' },
                    { source: 'action-9', target: 'action-10' },
                    { source: 'action-10', target: 'action-11' },
                    { source: 'action-11', target: 'action-12' },
                ],
            ),
        },
        {
            name: 'Fallback All-in-One — Pesan Tidak Dikenal',
            description:
                'Automation fallback terpisah (trigger: semua pesan). Menjawab saat pesan tidak dikenali dan mengarahkan kembali ke tombol Layanan CS atau Belajar LMS.',
            icon: MessageSquare,
            color: 'orange',
            actions: [
                {
                    type: 'condition',
                    conditions: [{ operator: 'contains', value: '' }],
                    conditions_relation: 'OR',
                },
                {
                    type: 'send_message',
                    text: 'Halo kak {{{senderName}}} 👋\n\nMaaf, kami kurang memahami pesan Anda:\n_"{{{senderMessage}}}"_\n\nSilakan pilih layanan di bawah ini:',
                    buttons: ['Layanan CS', 'Belajar LMS'],
                    footer_text: 'Pilih menu layanan',
                },
                { type: 'save_response', response_field: 'var5' },
            ],
            visual_graph: makeTemplateGraph(
                [
                    { x: 440, y: 280 },
                    { x: 860, y: 280 },
                    { x: 1280, y: 280 },
                ],
                [
                    { source: 'start', target: 'action-0' },
                    { source: 'action-0', target: 'action-1', label: 'semua pesan' },
                    { source: 'action-1', target: 'action-2' },
                ],
            ),
        },
    ];

    const loadTemplate = (templateIndex: number) => {
        const template = premadeTemplates[templateIndex];

        if (
            confirm(
                `Muat template "${template.name}"? Tindakan ini akan menggantikan langkah-langkah alur saat ini.`,
            )
        ) {
            const nextActions = template.actions.map((act) => ({
                ...createAction(act.type as ActionType, groups),
                ...act,
            })) as Action[];
            const nextGraph = mergeSavedGraph(
                buildGraph(nextActions, groups),
                template.visual_graph ?? null,
            );

            setFormData({
                name: template.name,
                actions: nextActions,
                visual_graph: template.visual_graph ?? null,
            });
            setNodes(nextGraph.nodes);
            setEdges(nextGraph.edges);
            setSelectedActionIndex(0);
            setSimulatedNodeStatuses({});
            toast.success('Template berhasil dimuat');
        }
    };

    const handleSimulateMessage = async (messageText: string) => {
        if (!messageText.trim()) {
            return;
        }

        setSimulatorMessages((prev) => [
            ...prev,
            { sender: 'user', text: messageText },
        ]);
        setSimulatorInput('');
        setIsSimulating(true);

        const actions = formData.actions;
        const newStatuses: Record<
            number,
            'active' | 'success' | 'failed' | 'idle'
        > = {};
        setSimulatedNodeStatuses({});

        const delay = (ms: number) =>
            new Promise((resolve) => setTimeout(resolve, ms));
        const userName = 'Budi';
        const userMobile = '+6281234567890';

        const replaceTokens = (text: string) => {
            return text
                .replaceAll('{{{senderName}}}', userName)
                .replaceAll('{{{senderMobile}}}', userMobile)
                .replaceAll('{{{senderMessage}}}', messageText);
        };

        const matchCondition = (action: Action) => {
            let isMatched = false;
            let matchedConditionIndex: number | null = null;
            const condList = action.conditions || [];
            const relation = action.conditions_relation || 'AND';

            const matchSingle = (operator: string, val: string) => {
                const normalizedMsg = messageText.toLowerCase().trim();
                const expected = val.toLowerCase().trim();

                if (operator === 'equals') {
                    return normalizedMsg === expected;
                } else if (operator === 'starts_with') {
                    return normalizedMsg.startsWith(expected);
                } else if (operator === 'ends_with') {
                    return normalizedMsg.endsWith(expected);
                }

                return normalizedMsg.includes(expected);
            };

            if (condList.length > 0) {
                if (relation === 'OR') {
                    matchedConditionIndex = condList.findIndex((c) =>
                        matchSingle(c.operator, c.value),
                    );
                    isMatched = matchedConditionIndex !== -1;
                } else {
                    isMatched = condList.every((c) =>
                        matchSingle(c.operator, c.value),
                    );
                    matchedConditionIndex = isMatched ? 0 : null;
                }
            } else {
                const cond = action.condition || '';
                const normalizedMsg = messageText.toLowerCase().trim();
                const matchRegex =
                    /^(?:\{\{\{senderMessage\}\}\}|message)\s+(contains|equals|starts_with|ends_with)\s+(.+)$/i;
                const matchMatches = cond.match(matchRegex);

                if (matchMatches) {
                    const operator = matchMatches[1].toLowerCase();
                    const expected = matchMatches[2]
                        .replace(/^['"]|['"]$/g, '')
                        .toLowerCase()
                        .trim();
                    isMatched = matchSingle(operator, expected);
                } else {
                    isMatched = normalizedMsg.includes(
                        cond.toLowerCase().trim(),
                    );
                }

                matchedConditionIndex = isMatched ? 0 : null;
            }

            const description =
                condList.length > 0
                    ? condList
                          .map((c) => `[${c.operator}: ${c.value}]`)
                          .join(` ${relation === 'OR' ? 'atau' : 'dan'} `)
                    : action.condition || '';

            return { isMatched, matchedConditionIndex, description };
        };

        const executeAction = async (index: number) => {
            const action = actions[index];

            if (!action) {
                return null;
            }

            newStatuses[index] = 'active';
            setSimulatedNodeStatuses({ ...newStatuses });
            await delay(1200);

            if (action.type === 'condition') {
                const { isMatched, matchedConditionIndex, description } =
                    matchCondition(action);

                if (!isMatched) {
                    newStatuses[index] = 'failed';
                    setSimulatedNodeStatuses({ ...newStatuses });
                    setSimulatorMessages((prev) => [
                        ...prev,
                        {
                            sender: 'system',
                            text: `Alur berhenti: tidak ada kondisi yang cocok (${description})`,
                        },
                    ]);

                    return null;
                }

                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Kondisi cocok. Cabang ${(matchedConditionIndex ?? 0) + 1} dipilih.`,
                    },
                ]);

                return matchedConditionIndex ?? 0;
            } else if (action.type === 'send_message') {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                const formattedButtons = (action.buttons || []).map((btn, btnIdx) => ({
                    id: typeof btn === 'object' && btn.id ? btn.id : `btn_${btnIdx + 1}`,
                    title: typeof btn === 'object' ? btn.title : String(btn),
                }));
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'bot',
                        text: replaceTokens(action.text || ''),
                        buttons: formattedButtons.length > 0 ? formattedButtons : undefined,
                    },
                ]);
            } else if (action.type === 'send_email') {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Aksi email: kirim ke ${action.email_to || 'support@example.com'} dengan subjek "${action.subject || ''}"`,
                    },
                ]);
            } else if (action.type === 'http_request') {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Aksi HTTP (${action.method || 'POST'}): ${action.url || ''}`,
                    },
                ]);
            } else if (action.type === 'lms_action') {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                const epLabel = action.lms_endpoint || 'auto';
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'bot',
                        text: `[LMS Natagara - Mode: ${epLabel}] Hubungkan ke ${action.lms_base_url || 'LMS'} dan kirimkan data pembelajaran/verifikasi ke WhatsApp.`,
                    },
                ]);
            } else if (action.type === 'google_sheets') {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Aksi Google Sheets: simpan ke "${action.sheet_name || 'Sheet1'}"`,
                    },
                ]);
            } else if (action.type === 'assign_agent') {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Aksi agen CS: tugaskan ke "${action.agent_name || ''}"`,
                    },
                ]);
            } else if (action.type === 'save_response') {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Aksi simpan: respons disimpan ke field ${action.response_field || 'notes'}`,
                    },
                ]);
            } else if (
                action.type === 'add_to_group' ||
                action.type === 'remove_from_group'
            ) {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
                const groupName =
                    groups.find((g) => g.id === Number(action.group_id))
                        ?.name || 'Unselected group';
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Aksi grup kontak: ${action.type === 'add_to_group' ? 'tambahkan pelanggan ke' : 'hapus pelanggan dari'} "${groupName}"`,
                    },
                ]);
            } else if (action.type === 'delay') {
                const seconds = action.delay_seconds || 5;
                setSimulatorMessages((prev) => [
                    ...prev,
                    {
                        sender: 'system',
                        text: `Aksi jeda: tunggu selama ${seconds} detik...`,
                    },
                ]);
                await delay(seconds * 1000);
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
            } else {
                newStatuses[index] = 'success';
                setSimulatedNodeStatuses({ ...newStatuses });
            }

            return undefined;
        };

        const executeNode = async (
            nodeId: string,
            visited = new Set<string>(),
        ) => {
            if (visited.has(nodeId)) {
                return;
            }

            visited.add(nodeId);

            const currentNode = nodes.find((node) => node.id === nodeId);
            let branchIndex: number | null | undefined;

            if (nodeId !== 'start') {
                const actionIndex =
                    typeof currentNode?.data.actionIndex === 'number'
                        ? currentNode.data.actionIndex
                        : null;

                if (actionIndex === null) {
                    return;
                }

                branchIndex = await executeAction(actionIndex);

                if (branchIndex === null) {
                    return;
                }
            }

            let childEdges = edges.filter(
                (edge) => edge.source === nodeId && edge.target,
            );

            if (branchIndex !== undefined && branchIndex !== null) {
                const currentAction = typeof currentNode?.data.actionIndex === 'number'
                    ? formData.actions[currentNode.data.actionIndex]
                    : null;
                const matchedCond = currentAction?.conditions?.[branchIndex];
                const matchedVal = (matchedCond?.value || '').toLowerCase().trim();
                const lowerMsg = messageText.toLowerCase().trim();

                // Bersihkan emoji untuk pencocokan teks
                const cleanMsg = lowerMsg.replace(/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu, '').trim();

                // 1. Cek apakah ada edge yang labelnya cocok dengan pesan user (teks tombol)
                let matchedEdge = childEdges.find((edge) => {
                    const label = String(edge.label || '').toLowerCase().trim();
                    if (!label) return false;
                    const cleanLabel = label.replace(/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/gu, '').trim();
                    return (
                        (cleanMsg && cleanLabel && (cleanMsg.includes(cleanLabel) || cleanLabel.includes(cleanMsg))) ||
                        lowerMsg.includes(label) ||
                        label.includes(lowerMsg)
                    );
                });

                // 2. Cek apakah ada edge yang labelnya cocok dengan kata kunci kondisi
                if (!matchedEdge && matchedVal) {
                    matchedEdge = childEdges.find((edge) => {
                        const label = String(edge.label || '').toLowerCase().trim();
                        return label.includes(matchedVal);
                    });
                }

                if (matchedEdge) {
                    childEdges = [matchedEdge];
                } else if (childEdges[branchIndex]) {
                    childEdges = [childEdges[branchIndex]];
                } else {
                    childEdges = childEdges.length > 0 ? [childEdges[0]] : [];
                }
            }

            for (const edge of childEdges) {
                await executeNode(edge.target, visited);
            }
        };

        await executeNode('start');

        setIsSimulating(false);
    };

    const insertVariable = (token: string) => {
        if (selectedActionIndex === null || !selectedAction) {
            return;
        }

        if (selectedAction.type === 'send_message') {
            handleUpdateAction(selectedActionIndex, {
                text: (selectedAction.text || '') + token,
            });
        } else if (selectedAction.type === 'send_email') {
            handleUpdateAction(selectedActionIndex, {
                text: (selectedAction.text || '') + token,
            });
        } else if (selectedAction.type === 'http_request') {
            handleUpdateAction(selectedActionIndex, {
                body: (selectedAction.body || '') + token,
            });
        }

        toast.success('Variable inserted');
    };

    const exportCurrentFlow = () => {
        const payload = {
            version: 1,
            type: 'natagara.automation_flow',
            flow: {
                name: formData.name || 'Untitled Flow',
                trigger_type: 'keyword',
                trigger_keyword: '*',
                trigger_match_type: 'contains',
                actions: formData.actions,
                visual_graph: serializeGraph(nodes, edges),
                is_active: flow?.is_active ?? false,
            },
        };
        const blob = new Blob([JSON.stringify(payload, null, 2)], {
            type: 'application/json',
        });
        const url = URL.createObjectURL(blob);
        const filename = `${
            (formData.name || 'automation-flow')
                .toLowerCase()
                .replace(/[^a-z0-9]+/g, '-')
                .replace(/^-|-$/g, '') || 'automation-flow'
        }.json`;
        const link = document.createElement('a');

        link.href = url;
        link.download = filename;
        link.click();
        URL.revokeObjectURL(url);
    };

    const importIntoCurrentFlow = async (file: File | null) => {
        if (!file) {
            return;
        }

        try {
            const payload = JSON.parse(await file.text()) as {
                flow?: Partial<FlowFormData>;
            } & Partial<FlowFormData>;
            const importedFlow = payload.flow ?? payload;
            const importedActions = Array.isArray(importedFlow.actions)
                ? importedFlow.actions
                : [];

            setFormData({
                name:
                    typeof importedFlow.name === 'string'
                        ? importedFlow.name
                        : formData.name,
                actions: importedActions as Action[],
                visual_graph: importedFlow.visual_graph ?? null,
            });
            const importedGraph = mergeSavedGraph(
                buildGraph(importedActions as Action[], groups),
                importedFlow.visual_graph ?? null,
            );
            setNodes(importedGraph.nodes);
            setEdges(importedGraph.edges);
            setSelectedActionIndex(importedActions.length > 0 ? 0 : null);
            toast.success('Flow loaded into the editor');
        } catch {
            toast.error('Invalid flow file');
        } finally {
            if (importInputRef.current) {
                importInputRef.current.value = '';
            }
        }
    };

    const submitFlow = () => {
        if (!formData.name.trim()) {
            toast.error('Harap beri nama alur terlebih dahulu pada bilah atas.');

            return;
        }

        if (formData.actions.length === 0) {
            toast.error('Tambahkan setidaknya satu node ke dalam alur.');

            return;
        }

        const payload = {
            ...formData,
            visual_graph: serializeGraph(nodes, edges),
        } as unknown as RequestPayload;

        setIsProcessing(true);

        if (flow) {
            router.put(updateAutomation.url(flow.id), payload, {
                onSuccess: () => toast.success('Alur berhasil diperbarui!'),
                onError: (errors) => {
                    const firstMsg = Object.values(errors)[0] as string | undefined;
                    toast.error(firstMsg || 'Gagal memperbarui alur. Periksa kelengkapan input.');
                },
                onFinish: () => setIsProcessing(false),
            });

            return;
        }

        router.post(storeAutomation.url(), payload, {
            onSuccess: () => toast.success('Alur berhasil dibuat!'),
            onError: (errors) => {
                const firstMsg = Object.values(errors)[0] as string | undefined;
                toast.error(firstMsg || 'Gagal menyimpan alur. Periksa kelengkapan input.');
            },
            onFinish: () => setIsProcessing(false),
        });
    };

    const renderActionEditor = () => {
        if (selectedActionIndex === null || !selectedAction) {
            return null;
        }

        const item = actionCatalogItem(selectedAction.type);
        const Icon = item.icon;

        return (
            <div className="space-y-4">
                <div className="flex items-center justify-between gap-3 border-b pb-3">
                    <div className="flex items-center gap-3">
                        <div
                            className={`flex h-10 w-10 items-center justify-center rounded-xl ${colorClasses[item.color]}`}
                        >
                            <Icon className="h-5 w-5" />
                        </div>
                        <div>
                            <div className="text-sm font-black text-zinc-950 dark:text-white">
                                {item.title}
                            </div>
                            <div className="text-[11px] font-semibold text-zinc-500">
                                {item.description}
                            </div>
                        </div>
                    </div>
                    <Button
                        className="h-8 w-8 p-0 text-rose-600 hover:bg-rose-50"
                        type="button"
                        variant="ghost"
                        onClick={() => handleRemoveAction(selectedActionIndex)}
                    >
                        <Trash2 className="h-4 w-4" />
                    </Button>
                </div>

                {/* Clickable Quick Variables */}
                {['send_message', 'send_email', 'http_request'].includes(
                    selectedAction.type,
                ) && (
                    <div className="space-y-1">
                        <span className="text-xs font-bold text-zinc-500">
                            Sisipkan variabel cepat:
                        </span>
                        <div className="flex flex-wrap gap-1.5">
                            {variables.map((v) => (
                                <button
                                    key={v.token}
                                    type="button"
                                    onClick={() => insertVariable(v.token)}
                                    className="rounded-md border border-emerald-200 bg-emerald-50 px-2 py-1 text-[10px] font-bold text-emerald-700 transition hover:bg-emerald-100"
                                >
                                    {v.label}
                                </button>
                            ))}
                        </div>
                    </div>
                )}

                {selectedAction.type === 'send_message' && (
                    <div className="space-y-3">
                        <div className="space-y-1.5">
                            <Label className="text-xs font-bold">
                                Teks Pesan
                            </Label>
                            <Textarea
                                className="min-h-24 text-xs"
                                value={selectedAction.text ?? ''}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        text: event.target.value,
                                    })
                                }
                                placeholder="Tulis balasan pesan WhatsApp di sini..."
                            />
                        </div>

                        {/* WhatsApp Interactive Buttons */}
                        <div className="space-y-2 rounded-xl border border-emerald-600/20 bg-emerald-50/50 p-3 dark:bg-emerald-950/20">
                            <div className="flex items-center justify-between">
                                <div>
                                    <Label className="text-xs font-bold text-emerald-900 dark:text-emerald-200">
                                        Tombol Pilihan (Maks. 3)
                                    </Label>
                                    <p className="text-[10px] text-zinc-500 dark:text-zinc-400">
                                        User tinggal klik di WhatsApp tanpa perlu mengetik
                                    </p>
                                </div>
                                {(selectedAction.buttons?.length ?? 0) < 3 && (
                                    <Button
                                        type="button"
                                        variant="outline"
                                        size="sm"
                                        className="h-7 text-[11px] font-bold text-emerald-700 hover:bg-emerald-100 dark:text-emerald-300"
                                        onClick={() => {
                                            const currentBtns = selectedAction.buttons ?? [];
                                            const nextBtns = [
                                                ...currentBtns,
                                                `Pilihan ${(currentBtns.length + 1)}`,
                                            ];
                                            handleUpdateAction(selectedActionIndex, {
                                                buttons: nextBtns,
                                            });
                                        }}
                                    >
                                        + Tombol
                                    </Button>
                                )}
                            </div>

                            <div className="space-y-1.5">
                                {(selectedAction.buttons || []).map((btn, btnIdx) => {
                                    const btnTitle = typeof btn === 'string' ? btn : (btn.title || '');
                                    return (
                                        <div key={btnIdx} className="flex items-center gap-2">
                                            <span className="text-[11px] font-bold text-zinc-400">
                                                {btnIdx + 1}.
                                            </span>
                                            <Input
                                                className="h-8 text-xs font-semibold"
                                                maxLength={20}
                                                value={btnTitle}
                                                placeholder="Judul tombol (maks 20 huruf)"
                                                onChange={(e) => {
                                                    const updatedBtns = [...(selectedAction.buttons || [])];
                                                    updatedBtns[btnIdx] = e.target.value;
                                                    handleUpdateAction(selectedActionIndex, {
                                                        buttons: updatedBtns,
                                                    });
                                                }}
                                            />
                                            <Button
                                                type="button"
                                                variant="ghost"
                                                size="sm"
                                                className="h-8 w-8 p-0 text-rose-500 hover:bg-rose-50 hover:text-rose-700"
                                                onClick={() => {
                                                    const updatedBtns = (selectedAction.buttons || []).filter(
                                                        (_, idx) => idx !== btnIdx
                                                    );
                                                    handleUpdateAction(selectedActionIndex, {
                                                        buttons: updatedBtns,
                                                    });
                                                }}
                                            >
                                                ✕
                                            </Button>
                                        </div>
                                    );
                                })}

                                {(selectedAction.buttons?.length ?? 0) === 0 && (
                                    <p className="text-[11px] italic text-zinc-400">
                                        Belum ada tombol (pesan akan terkirim sebagai teks biasa).
                                    </p>
                                )}
                            </div>
                        </div>

                        <div className="space-y-1">
                            <Label className="text-[11px] font-bold text-zinc-500">
                                Footer Teks (Opsional)
                            </Label>
                            <Input
                                className="h-8 text-xs"
                                value={selectedAction.footer_text ?? ''}
                                onChange={(e) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        footer_text: e.target.value,
                                    })
                                }
                                placeholder="Contoh: Ketik 'menu' untuk kembali"
                            />
                        </div>
                    </div>
                )}

                {selectedAction.type === 'send_email' && (
                    <div className="space-y-2">
                        <div>
                            <Label className="text-xs font-bold">
                                Email Tujuan
                            </Label>
                            <Input
                                className="h-9 text-xs"
                                value={selectedAction.email_to ?? ''}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        email_to: event.target.value,
                                    })
                                }
                                placeholder="email@contoh.com"
                            />
                        </div>
                        <div>
                            <Label className="text-xs font-bold">Subjek</Label>
                            <Input
                                className="h-9 text-xs"
                                value={selectedAction.subject ?? ''}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        subject: event.target.value,
                                    })
                                }
                                placeholder="Subjek email"
                            />
                        </div>
                        <div>
                            <Label className="text-xs font-bold">
                                Isi Email
                            </Label>
                            <Textarea
                                className="min-h-20 text-xs"
                                value={selectedAction.text ?? ''}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        text: event.target.value,
                                    })
                                }
                                placeholder="Konten isi email"
                            />
                        </div>
                    </div>
                )}

                {selectedAction.type === 'http_request' && (
                    <div className="space-y-2">
                        <Label className="text-xs font-bold">
                            Permintaan HTTP (Webhook)
                        </Label>
                        <div className="grid grid-cols-[80px_1fr] gap-1.5">
                            <select
                                className="h-9 rounded-md border bg-background px-2 text-xs font-bold"
                                value={selectedAction.method ?? 'POST'}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        method: event.target
                                            .value as Action['method'],
                                    })
                                }
                            >
                                <option value="GET">GET</option>
                                <option value="POST">POST</option>
                                <option value="PUT">PUT</option>
                                <option value="PATCH">PATCH</option>
                                <option value="DELETE">DELETE</option>
                            </select>
                            <Input
                                className="h-9 text-xs"
                                value={selectedAction.url ?? ''}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        url: event.target.value,
                                    })
                                }
                                placeholder="https://api.contoh.com/webhook"
                            />
                        </div>
                        <div>
                            <Label className="text-xs font-bold">
                                Body (JSON)
                            </Label>
                            <Textarea
                                className="min-h-20 font-mono text-[10px] leading-tight"
                                dir="ltr"
                                value={selectedAction.body ?? ''}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        body: event.target.value,
                                    })
                                }
                            />
                        </div>
                    </div>
                )}

                {selectedAction.type === 'lms_action' && (
                    <div className="space-y-3">
                        <div className="space-y-1.5">
                            <Label className="text-xs font-bold">
                                Tipe Permintaan / Fitur LMS
                            </Label>
                            <select
                                className="h-9 w-full rounded-md border bg-background px-3 text-xs font-semibold"
                                value={selectedAction.lms_endpoint ?? 'auto'}
                                onChange={(event) =>
                                    handleUpdateAction(selectedActionIndex, {
                                        lms_endpoint: event.target
                                            .value as Action['lms_endpoint'],
                                    })
                                }
                            >
                                <option value="auto">
                                    ⚡ Deteksi Otomatis (Cek Kode Verifikasi / Keyword / Summary)
                                </option>
                                <option value="verify">
                                    🔑 Verifikasi Akun (Input Kode 6 Digit)
                                </option>
                                <option value="summary">
                                    📊 Ringkasan Kelas & Menu Belajar
                                </option>
                                <option value="courses">
                                    📚 Daftar Kursus yang Diikuti
                                </option>
                                <option value="select_course">
                                    📖 Pilih Kelas & Menu Pembelajaran
                                </option>
                                <option value="outline">
                                    📑 Silabus Bab & Materi Pelajaran
                                </option>
                                <option value="lesson">
                                    📖 Baca Materi Pelajaran (WhatsApp Format)
                                </option>
                                <option value="complete_lesson">
                                    🎉 Tandai Materi Selesai & Klaim Poin
                                </option>
                                <option value="quiz">
                                    🎯 Detail & Link Pengerjaan Kuis
                                </option>
                                <option value="tasks">
                                    📝 Agenda & Tugas Belajar Pending
                                </option>
                                <option value="certificates">
                                    🎓 Sertifikat Kelulusan & Unduh PDF
                                </option>
                                <option value="search">
                                    🔍 Pencarian Materi Pembelajaran LMS
                                </option>
                            </select>
                            <p className="text-[11px] leading-relaxed text-zinc-500">
                                Mode <strong>Deteksi Otomatis</strong> akan memverifikasi jika pesan mengandung 6 digit, atau mengirimkan ringkasan kelas / tugas sesuai pesan pengguna.
                            </p>
                        </div>

                        {/* Collapsible / Optional Advanced Credentials */}
                        <details className="group rounded-xl border border-zinc-200 bg-zinc-50/70 p-3 text-xs dark:border-zinc-800 dark:bg-zinc-900/40">
                            <summary className="flex cursor-pointer items-center justify-between font-bold text-zinc-700 select-none dark:text-zinc-300">
                                <span>Pengaturan Lanjutan (Opsional)</span>
                                <span className="text-[10px] text-zinc-400 group-open:rotate-180 transition-transform duration-200">
                                    ▼
                                </span>
                            </summary>
                            <div className="mt-3 space-y-2.5 pt-2 border-t border-zinc-200/60 dark:border-zinc-800/60">
                                <div className="space-y-1">
                                    <Label className="text-[11px] font-semibold text-zinc-600 dark:text-zinc-400">
                                        Base URL LMS (Kustom)
                                    </Label>
                                    <Input
                                        className="h-8 text-xs"
                                        value={selectedAction.lms_base_url ?? ''}
                                        onChange={(event) =>
                                            handleUpdateAction(selectedActionIndex, {
                                                lms_base_url: event.target.value,
                                            })
                                        }
                                        placeholder="Default: http://lms-pakandi.test"
                                    />
                                </div>
                                <div className="space-y-1">
                                    <Label className="text-[11px] font-semibold text-zinc-600 dark:text-zinc-400">
                                        API Key LMS (Kustom)
                                    </Label>
                                    <Input
                                        className="h-8 font-mono text-xs"
                                        type="password"
                                        value={selectedAction.lms_api_key ?? ''}
                                        onChange={(event) =>
                                            handleUpdateAction(selectedActionIndex, {
                                                lms_api_key: event.target.value,
                                            })
                                        }
                                        placeholder="Default dari konfigurasi server"
                                    />
                                    <p className="text-[10px] text-zinc-400">
                                        Kosongkan untuk menggunakan API Key default sistem.
                                    </p>
                                </div>
                            </div>
                        </details>
                    </div>
                )}

                {selectedAction.type === 'google_sheets' && (
                    <div className="space-y-1.5">
                        <Label className="text-xs font-bold">
                            Nama Google Sheet
                        </Label>
                        <Input
                            className="h-9 text-xs"
                            value={selectedAction.sheet_name ?? ''}
                            onChange={(event) =>
                                handleUpdateAction(selectedActionIndex, {
                                    sheet_name: event.target.value,
                                })
                            }
                            placeholder="Leads"
                        />
                    </div>
                )}
                {selectedAction.type === 'assign_agent' && (
                    <div className="space-y-1.5">
                        <Label className="text-xs font-bold">
                            Nama Agen atau Departemen
                        </Label>
                        <Input
                            className="h-9 text-xs"
                            value={selectedAction.agent_name ?? ''}
                            onChange={(event) =>
                                handleUpdateAction(selectedActionIndex, {
                                    agent_name: event.target.value,
                                })
                            }
                            placeholder="Tim Penjualan"
                        />
                    </div>
                )}
                {selectedAction.type === 'condition' &&
                    (() => {
                        const conds = selectedAction.conditions || [];
                        const relation =
                            selectedAction.conditions_relation || 'AND';

                        const updateRelation = (rel: 'AND' | 'OR') => {
                            handleUpdateAction(selectedActionIndex, {
                                conditions_relation: rel,
                            });
                        };

                        const updateCondItem = (
                            idx: number,
                            fields: Partial<{
                                operator:
                                    | 'contains'
                                    | 'equals'
                                    | 'starts_with'
                                    | 'ends_with';
                                value: string;
                            }>,
                        ) => {
                            const newConds = [...conds];
                            newConds[idx] = { ...newConds[idx], ...fields };

                            const first = newConds[0];
                            const legacyStr = first
                                ? `message ${first.operator} ${first.value}`
                                : '';

                            handleUpdateAction(selectedActionIndex, {
                                conditions: newConds,
                                condition: legacyStr,
                            });
                        };

                        const addCondItem = () => {
                            const newConds = [
                                ...conds,
                                { operator: 'contains' as const, value: '' },
                            ];
                            handleUpdateAction(selectedActionIndex, {
                                conditions: newConds,
                            });
                        };

                        const removeCondItem = (idx: number) => {
                            const newConds = conds.filter((_, i) => i !== idx);
                            const first = newConds[0];
                            const legacyStr = first
                                ? `message ${first.operator} ${first.value}`
                                : '';
                            handleUpdateAction(selectedActionIndex, {
                                conditions: newConds,
                                condition: legacyStr,
                            });
                        };

                        return (
                            <div className="space-y-4">
                                <div className="space-y-1">
                                    <Label className="text-xs font-bold">
                                        Hubungan Kondisi
                                    </Label>
                                    <select
                                        className="h-9 w-full rounded-md border bg-background px-3 text-xs font-semibold"
                                        value={relation}
                                        onChange={(e) =>
                                            updateRelation(
                                                e.target.value as 'AND' | 'OR',
                                            )
                                        }
                                    >
                                        <option value="AND">
                                            Semua kondisi harus terpenuhi (AND)
                                        </option>
                                        <option value="OR">
                                            Salah satu kondisi terpenuhi (OR)
                                        </option>
                                    </select>
                                </div>

                                <div className="space-y-3">
                                    <Label className="text-xs font-bold">
                                        Daftar Kondisi
                                    </Label>
                                    {conds.map((cond, idx) => (
                                        <div
                                            key={idx}
                                            className="space-y-2 rounded-xl border border-zinc-200 bg-zinc-50 p-3 dark:border-zinc-800 dark:bg-zinc-900/60"
                                        >
                                            <div className="flex items-center justify-between">
                                                <div className="text-[10px] font-bold text-zinc-400">
                                                    Kondisi #{idx + 1}
                                                </div>
                                                {conds.length > 1 && (
                                                    <button
                                                        type="button"
                                                        onClick={() =>
                                                            removeCondItem(idx)
                                                        }
                                                        className="text-[10px] font-bold text-rose-500 hover:text-rose-700"
                                                    >
                                                        Hapus
                                                    </button>
                                                )}
                                            </div>

                                            <div className="space-y-1">
                                                <select
                                                    className="h-8 w-full rounded-md border bg-background px-2 text-[11px] font-semibold"
                                                    value={cond.operator}
                                                    onChange={(e) =>
                                                        updateCondItem(idx, {
                                                            operator: e.target
                                                                .value as any,
                                                        })
                                                    }
                                                >
                                                    <option value="contains">
                                                        Mengandung kata
                                                    </option>
                                                    <option value="equals">
                                                        Sama persis dengan
                                                    </option>
                                                    <option value="starts_with">
                                                        Diawali dengan
                                                    </option>
                                                    <option value="ends_with">
                                                        Diakhiri dengan
                                                    </option>
                                                </select>
                                            </div>

                                            <div className="space-y-1">
                                                <Input
                                                    className="h-8 text-[11px]"
                                                    value={cond.value}
                                                    onChange={(e) =>
                                                        updateCondItem(idx, {
                                                            value: e.target
                                                                .value,
                                                        })
                                                    }
                                                    placeholder="Kata kunci atau nilai yang diharapkan..."
                                                />
                                            </div>
                                        </div>
                                    ))}
                                </div>

                                <div className="rounded-xl border border-emerald-200 bg-emerald-50 p-3 text-[11px] leading-relaxed font-bold text-emerald-800 dark:border-emerald-900/70 dark:bg-emerald-950/30 dark:text-emerald-300">
                                    Hubungkan setiap cabang kondisi pada kanvas. Tarik garis koneksi dari node kondisi ini ke pesan atau aksi yang ingin dipicu. Garis keluar mengikuti urutan kondisi: kondisi #1 menggunakan koneksi pertama, kondisi #2 menggunakan koneksi kedua, dan seterusnya.
                                </div>

                                <Button
                                    type="button"
                                    onClick={addCondItem}
                                    variant="outline"
                                    className="h-8 w-full border-dashed border-emerald-300 text-[11px] text-emerald-700 hover:bg-emerald-50 dark:border-emerald-800 dark:text-emerald-400"
                                >
                                    + Tambah kondisi lainnya
                                </Button>
                            </div>
                        );
                    })()}
                {selectedAction.type === 'delay' && (
                    <div className="space-y-1.5">
                        <Label className="text-xs font-bold">
                            Waktu jeda penundaan (detik)
                        </Label>
                        <Input
                            className="h-9 text-xs"
                            min={1}
                            type="number"
                            value={selectedAction.delay_seconds ?? 60}
                            onChange={(event) =>
                                handleUpdateAction(selectedActionIndex, {
                                    delay_seconds: Number(event.target.value),
                                })
                            }
                        />
                    </div>
                )}

                {selectedAction.type === 'save_response' && (
                    <div className="space-y-1.5">
                        <Label className="text-xs font-bold">
                            Simpan respons ke dalam
                        </Label>
                        <select
                            className="h-9 w-full rounded-md border bg-background px-3 text-xs"
                            value={selectedAction.response_field ?? 'notes'}
                            onChange={(event) =>
                                handleUpdateAction(selectedActionIndex, {
                                    response_field: event.target
                                        .value as Action['response_field'],
                                })
                            }
                        >
                            <option value="notes">Catatan Kontak</option>
                            <option value="var1">Variabel 1</option>
                            <option value="var2">Variabel 2</option>
                            <option value="var3">Variabel 3</option>
                            <option value="var4">Variabel 4</option>
                            <option value="var5">Variabel 5</option>
                        </select>
                    </div>
                )}

                {(selectedAction.type === 'add_to_group' ||
                    selectedAction.type === 'remove_from_group') && (
                    <div className="space-y-1.5">
                        <Label className="text-xs font-bold">
                            Pilih grup kontak
                        </Label>
                        <select
                            className="h-9 w-full rounded-md border bg-background px-3 text-xs"
                            value={selectedAction.group_id ?? ''}
                            onChange={(event) =>
                                handleUpdateAction(selectedActionIndex, {
                                    group_id: Number(event.target.value),
                                })
                            }
                        >
                            {groups.map((group) => (
                                <option key={group.id} value={group.id}>
                                    {group.name}
                                </option>
                            ))}
                        </select>
                    </div>
                )}

                {selectedAction.type === 'disable_autoreply' && (
                    <div className="rounded-xl bg-orange-50 px-4 py-3 text-xs font-semibold text-orange-700 dark:bg-orange-950/30 dark:text-orange-300">
                        Node ini akan menjeda balasan pesan otomatis pada tahapan alur ini.
                    </div>
                )}
            </div>
        );
    };

    return (
        <div
            className={`fixed inset-0 z-40 grid bg-[#eef2f5] transition-all duration-300 dark:bg-zinc-950 ${isSidebarOpen ? 'lg:grid-cols-[360px_1fr]' : 'lg:grid-cols-[0_1fr]'}`}
            dir="ltr"
        >
            {isSidebarOpen && (
                <button
                    className="fixed inset-0 z-30 bg-zinc-950/40 lg:hidden"
                    type="button"
                    onClick={() => setIsSidebarOpen(false)}
                />
            )}

            {/* Floating Sidebar Toggle Handle (Desktop Only) */}
            <button
                type="button"
                onClick={() => setIsSidebarOpen(!isSidebarOpen)}
                className={`absolute top-1/2 z-50 hidden h-16 w-5 -translate-y-1/2 items-center justify-center rounded-r-xl border-y border-r bg-white text-zinc-500 shadow-md transition-all duration-300 hover:bg-zinc-50 hover:text-emerald-600 lg:flex dark:border-zinc-800 dark:bg-zinc-900 dark:hover:bg-zinc-800 ${
                    isSidebarOpen ? 'left-[360px]' : 'left-0'
                }`}
                title={isSidebarOpen ? 'Tutup bilah sisi' : 'Buka bilah sisi'}
            >
                {isSidebarOpen ? (
                    <ChevronLeft className="h-4 w-4" />
                ) : (
                    <ChevronRight className="h-4 w-4" />
                )}
            </button>

            <aside
                className={`fixed inset-y-0 left-0 z-40 flex min-h-0 w-[min(360px,calc(100vw-24px))] flex-col border-r bg-white transition-all duration-300 lg:relative lg:z-auto dark:bg-zinc-950 ${
                    isSidebarOpen
                        ? 'translate-x-0 lg:w-[360px]'
                        : '-translate-x-full lg:pointer-events-none lg:w-0 lg:translate-x-0 lg:opacity-0'
                }`}
            >
                {/* Sidebar Header */}
                <div className="border-b p-5 text-left">
                    <div className="flex items-start justify-between gap-4">
                        <div className="flex items-center gap-2">
                            <Link
                                className="flex h-9 w-9 items-center justify-center rounded-full text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-900"
                                href={automationsIndex.url()}
                            >
                                <ArrowLeft className="h-5 w-5" />
                            </Link>
                            <button
                                className="flex h-9 w-9 items-center justify-center rounded-full text-zinc-500 hover:bg-zinc-100 lg:hidden dark:hover:bg-zinc-900"
                                type="button"
                                onClick={() => setIsSidebarOpen(false)}
                            >
                                <PanelRightClose className="h-5 w-5" />
                            </button>
                        </div>
                        <div>
                            <div className="text-xl font-black">
                                Pilihan Alur
                            </div>
                            <p className="mt-1 text-xs font-semibold text-zinc-500">
                                Rancang alur dan otomatisasi pesan dengan mudah
                            </p>
                        </div>
                    </div>
                </div>

                {/* Tabs selection bar */}
                <div className="flex border-b bg-zinc-50 p-1 dark:bg-zinc-900/50">
                    <button
                        type="button"
                        onClick={() => setSidebarTab('nodes')}
                        className={`flex-1 rounded-lg py-2 text-center text-xs font-bold transition-all ${
                            sidebarTab === 'nodes'
                                ? 'bg-white text-emerald-600 shadow-xs dark:bg-zinc-950 dark:text-emerald-400'
                                : 'text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-300'
                        }`}
                    >
                        Node
                    </button>
                    <button
                        type="button"
                        onClick={() => setSidebarTab('templates')}
                        className={`flex-1 rounded-lg py-2 text-center text-xs font-bold transition-all ${
                            sidebarTab === 'templates'
                                ? 'bg-white text-emerald-600 shadow-xs dark:bg-zinc-950 dark:text-emerald-400'
                                : 'text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-300'
                        }`}
                    >
                        Template
                    </button>
                </div>

                {sidebarTab === 'nodes' ? (
                    <>
                        {/* Search and Imports section */}
                        <div className="space-y-3 border-b p-4">
                            <div className="relative">
                                <Search className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 text-zinc-400" />
                                <Input
                                    className="h-9 pl-9 text-xs"
                                    value={paletteSearch}
                                    onChange={(event) =>
                                        setPaletteSearch(event.target.value)
                                    }
                                    placeholder="Cari node dan alat alur..."
                                />
                            </div>
                            <div className="grid grid-cols-2 gap-2">
                                <input
                                    ref={importInputRef}
                                    accept="application/json,.json"
                                    className="hidden"
                                    type="file"
                                    onChange={(event) =>
                                        void importIntoCurrentFlow(
                                            event.target.files?.[0] ?? null,
                                        )
                                    }
                                />
                                <Button
                                    className="h-9 gap-2 text-xs"
                                    type="button"
                                    variant="outline"
                                    onClick={() =>
                                        importInputRef.current?.click()
                                    }
                                >
                                    <Upload className="h-3.5 w-3.5" />
                                    Impor
                                </Button>
                                <Button
                                    className="h-9 gap-2 text-xs"
                                    type="button"
                                    variant="outline"
                                    onClick={exportCurrentFlow}
                                >
                                    <Download className="h-3.5 w-3.5" />
                                    Ekspor
                                </Button>
                            </div>
                        </div>

                        {/* Nodes Catalog */}
                        <div className="min-h-0 flex-1 overflow-y-auto p-4">
                            <div className="space-y-6">
                                {categories.map((category) => {
                                    const items = filteredCatalog.filter(
                                        (item) => item.category === category,
                                    );

                                    if (items.length === 0) {
                                        return null;
                                    }

                                    return (
                                        <section
                                            key={category}
                                            className="space-y-2.5"
                                        >
                                            <div className="flex items-center gap-3">
                                                <div className="h-px flex-1 bg-zinc-100 dark:bg-zinc-800" />
                                                <h3 className="text-[10px] font-black tracking-wide text-zinc-400 uppercase">
                                                    {{
                                                        Messages: 'Pesan',
                                                        Requests: 'Permintaan & Integrasi',
                                                        Inputs: 'Input & Data',
                                                        Logic: 'Logika & Alur',
                                                        Contacts: 'Kontak & Grup',
                                                    }[category] ?? category}
                                                </h3>
                                                <div className="h-px flex-1 bg-zinc-100 dark:bg-zinc-800" />
                                            </div>
                                            <div className="space-y-2">
                                                {items.map((item) => {
                                                    const Icon = item.icon;

                                                    return (
                                                        <button
                                                            key={item.type}
                                                            draggable
                                                            onDragStart={(
                                                                event,
                                                            ) => {
                                                                event.dataTransfer.setData(
                                                                    'application/reactflow',
                                                                    item.type,
                                                                );
                                                                event.dataTransfer.effectAllowed =
                                                                    'move';
                                                            }}
                                                            className="flex w-full cursor-grab items-center justify-between gap-3 rounded-xl border bg-white p-3 text-left shadow-xs transition hover:-translate-y-0.5 hover:border-emerald-300 hover:shadow-md active:cursor-grabbing dark:bg-zinc-950"
                                                            type="button"
                                                            onClick={() =>
                                                                handleAddAction(
                                                                    item.type,
                                                                )
                                                            }
                                                        >
                                                            <div
                                                                className={`flex h-10 w-10 items-center justify-center rounded-lg ${colorClasses[item.color] ?? colorClasses.emerald}`}
                                                            >
                                                                <Icon className="h-5 w-5" />
                                                            </div>
                                                            <div className="min-w-0 flex-1">
                                                                <div className="truncate text-xs font-black text-zinc-900 dark:text-zinc-50">
                                                                    {item.title}
                                                                </div>
                                                                <div className="mt-0.5 truncate text-[10px] font-semibold text-zinc-400">
                                                                    {
                                                                        item.description
                                                                    }
                                                                </div>
                                                            </div>
                                                        </button>
                                                    );
                                                })}
                                            </div>
                                        </section>
                                    );
                                })}
                            </div>
                        </div>
                    </>
                ) : (
                    /* Advanced Templates Tab */
                    <div className="min-h-0 flex-1 space-y-4 overflow-y-auto p-4">
                        {premadeTemplates.map((t, idx) => {
                            const Icon = t.icon;
                            const isFeatured = idx === 0;

                            return (
                                <div
                                    key={idx}
                                    className={`group relative overflow-hidden rounded-2xl border p-4 text-left transition-all duration-300 ${
                                        isFeatured
                                            ? 'border-emerald-500 bg-gradient-to-br from-emerald-50/80 via-white to-teal-50/50 shadow-sm hover:border-emerald-600 hover:shadow-md dark:border-emerald-500/50 dark:from-emerald-950/20 dark:via-zinc-900/60 dark:to-teal-950/20'
                                            : 'border-zinc-100 bg-white hover:border-emerald-400 hover:shadow-md dark:border-zinc-800 dark:bg-zinc-900/40'
                                    }`}
                                >
                                    {isFeatured && (
                                        <div className="mb-2.5 inline-flex items-center gap-1 rounded-full bg-emerald-600 px-2.5 py-0.5 text-[9px] font-extrabold text-white shadow-xs">
                                            ⭐ Rekomendasi Resmi Natagara
                                        </div>
                                    )}
                                    <div className="flex items-start justify-between gap-3">
                                        <div
                                            className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl ${colorClasses[t.color] ?? colorClasses.emerald}`}
                                        >
                                            <Icon className="h-5 w-5" />
                                        </div>
                                        <div className="min-w-0 flex-1">
                                            <h4 className="text-xs font-black text-zinc-800 transition-colors group-hover:text-emerald-600 dark:text-zinc-100">
                                                {t.name}
                                            </h4>
                                            <p className="mt-1 text-[10px] leading-relaxed font-semibold text-zinc-400">
                                                {t.description}
                                            </p>
                                        </div>
                                    </div>

                                    <div className="dark:border-zinc-850 mt-3.5 flex items-center justify-between border-t border-dashed border-zinc-100 pt-3">
                                        <span className="rounded-full bg-zinc-100 px-2 py-0.5 text-[9px] font-bold text-zinc-500 dark:bg-zinc-800">
                                            {t.actions.length} langkah • Siap Pakai
                                        </span>
                                        <Button
                                            type="button"
                                            onClick={() => loadTemplate(idx)}
                                            className={`h-7 px-3 text-[10px] font-bold ${
                                                isFeatured
                                                    ? 'bg-emerald-600 text-white hover:bg-emerald-700 shadow-xs'
                                                    : 'border border-emerald-200 bg-emerald-50 text-emerald-700 hover:bg-emerald-100 dark:border-emerald-800/50 dark:bg-emerald-950/20 dark:text-emerald-400'
                                            }`}
                                        >
                                            Gunakan template
                                        </Button>
                                    </div>
                                </div>
                            );
                        })}
                    </div>
                )}
            </aside>

            <main ref={reactFlowWrapper} className="relative min-h-0">
                <div className="absolute inset-x-0 top-0 z-20 flex items-center justify-between gap-2 border-b bg-white/70 px-3 py-3 backdrop-blur sm:px-5 dark:bg-zinc-950/70">
                    <div className="flex min-w-0 items-center gap-2">
                        {!isSidebarOpen && (
                            <button
                                className="flex h-10 w-10 shrink-0 items-center justify-center rounded-2xl bg-white text-zinc-600 shadow-sm hover:bg-zinc-50 dark:bg-zinc-900 dark:text-zinc-300"
                                type="button"
                                onClick={() => setIsSidebarOpen(true)}
                            >
                                <Menu className="h-5 w-5" />
                            </button>
                        )}
                        <div className="flex min-w-0 items-center gap-2 rounded-2xl bg-white px-4 py-2 shadow-sm dark:bg-zinc-900">
                            <Workflow className="h-4 w-4 text-emerald-600" />
                            <input
                                className="min-w-0 bg-transparent text-sm font-black text-zinc-700 outline-none placeholder:text-zinc-400 dark:text-zinc-200"
                                value={formData.name}
                                onChange={(event) =>
                                    setFormDataField('name', event.target.value)
                                }
                                placeholder="Beri nama alur ini..."
                            />
                        </div>
                    </div>
                    <div className="flex shrink-0 items-center gap-2">
                        <Button
                            type="button"
                            variant="outline"
                            onClick={() => setIsSimulatorOpen((prev) => !prev)}
                            className="h-10 gap-2 border-none bg-zinc-900 px-4 text-xs font-bold text-white hover:bg-zinc-800 dark:bg-zinc-800 dark:hover:bg-zinc-700"
                        >
                            Uji Alur Langsung
                        </Button>
                        <Button
                            asChild
                            className="hidden h-10 gap-2 text-xs sm:inline-flex"
                            type="button"
                            variant="outline"
                        >
                            <Link href={automationsIndex.url()}>Batal</Link>
                        </Button>
                        <Button
                            className="h-10 gap-2 bg-emerald-600 px-4 text-xs text-white hover:bg-emerald-700"
                            disabled={isProcessing}
                            type="button"
                            onClick={submitFlow}
                        >
                            <Check className="h-4 w-4" />
                            Simpan Alur
                        </Button>
                    </div>
                </div>

                {/* Quick-Start Template Banner when creating a new flow */}
                {!flow && formData.actions.length === 0 && (
                    <div className="absolute top-20 left-1/2 z-20 w-full max-w-2xl -translate-x-1/2 px-4 animate-in fade-in duration-300">
                        <div className="flex flex-col sm:flex-row items-center justify-between gap-4 rounded-3xl border border-emerald-300 bg-white/95 p-5 shadow-2xl backdrop-blur dark:border-emerald-700/60 dark:bg-zinc-900/95">
                            <div className="flex items-center gap-3.5">
                                <div className="flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-emerald-600 text-white shadow-md">
                                    <GraduationCap className="h-6 w-6" />
                                </div>
                                <div>
                                    <div className="flex items-center gap-2">
                                        <h3 className="text-sm font-black text-zinc-900 dark:text-white">
                                            Asisten Belajar Natagara
                                        </h3>
                                        <span className="rounded-full bg-emerald-100 px-2.5 py-0.5 text-[10px] font-extrabold text-emerald-800 dark:bg-emerald-950 dark:text-emerald-300">
                                            ⭐ Siap Pakai 1-Klik
                                        </span>
                                    </div>
                                    <p className="mt-1 text-xs text-zinc-600 dark:text-zinc-400">
                                        Bot WhatsApp otomatis: verifikasi kode 6-digit akun LMS, menu belajar, daftar kelas, materi, kuis, tugas, dan sertifikat tanpa perlu konfigurasi satu per satu.
                                    </p>
                                </div>
                            </div>
                            <Button
                                type="button"
                                onClick={() => loadTemplate(0)}
                                className="shrink-0 whitespace-nowrap rounded-xl bg-emerald-600 px-4 py-2.5 text-xs font-bold text-white hover:bg-emerald-700 shadow-md transition"
                            >
                                Gunakan Template Ini
                            </Button>
                        </div>
                    </div>
                )}

                {/* Floating Node Settings Drawer (Left Side) */}
                {selectedActionIndex !== null && selectedAction && (
                    <div className="absolute top-20 left-4 z-30 max-h-[calc(100vh-120px)] w-[350px] animate-in overflow-y-auto rounded-2xl border border-zinc-200 bg-white/95 p-5 text-left shadow-2xl backdrop-blur duration-300 slide-in-from-left dark:border-zinc-800 dark:bg-zinc-950/95">
                        <div className="mb-3 flex items-center justify-between">
                            <button
                                type="button"
                                onClick={() => setSelectedActionIndex(null)}
                                className="rounded-md bg-zinc-100 px-2 py-1 text-xs text-zinc-600 hover:bg-zinc-200 dark:bg-zinc-800"
                            >
                                Tutup
                            </button>
                            <span className="text-xs font-bold text-zinc-400">
                                Pengaturan langkah
                            </span>
                        </div>
                        {renderActionEditor()}
                    </div>
                )}

                {/* WhatsApp Interactive Simulator Panel */}
                {isSimulatorOpen && (
                    <div className="absolute bottom-4 left-4 z-30 flex h-[480px] w-[360px] animate-in flex-col overflow-hidden rounded-3xl border border-zinc-200 bg-zinc-50 shadow-2xl duration-300 slide-in-from-bottom dark:border-zinc-800 dark:bg-zinc-900">
                        {/* Mock Phone Header */}
                        <div className="flex items-center justify-between bg-[#075e54] p-4 text-white">
                            <button
                                type="button"
                                onClick={() => {
                                    setIsSimulatorOpen(false);
                                    setSimulatedNodeStatuses({});
                                }}
                                className="rounded-full bg-black/10 px-2.5 py-1 text-xs font-bold text-white hover:opacity-85"
                            >
                                Tutup
                            </button>
                            <div className="text-left">
                                <div className="flex items-center justify-start gap-1.5 text-sm font-black">
                                    <span>Bot Natagara</span>
                                    <span className="h-2.5 w-2.5 animate-ping rounded-full bg-emerald-400"></span>
                                </div>
                                <div className="text-[10px] opacity-75">
                                    Simulasi alur langsung
                                </div>
                            </div>
                        </div>

                        {/* Message Timeline */}
                        <div className="flex-1 space-y-3 overflow-y-auto bg-[#efeae2] p-4 dark:bg-zinc-950">
                            {simulatorMessages.map((msg, index) => {
                                if (msg.sender === 'system') {
                                    return (
                                        <div
                                            key={index}
                                            className="text-center"
                                        >
                                            <span className="inline-block max-w-[85%] rounded-xl bg-zinc-200/95 px-3 py-1.5 text-[10px] leading-relaxed font-bold text-zinc-700 dark:bg-zinc-800/90 dark:text-zinc-300">
                                                {msg.text}
                                            </span>
                                        </div>
                                    );
                                }

                                const isUser = msg.sender === 'user';

                                return (
                                    <div
                                        key={index}
                                        className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}
                                    >
                                        <div
                                            className={`max-w-[85%] rounded-2xl p-3 text-left text-xs leading-relaxed font-semibold shadow-sm ${
                                                isUser
                                                    ? 'rounded-tr-none bg-white text-zinc-900 dark:bg-zinc-900 dark:text-white'
                                                    : 'rounded-tl-none border-l-2 border-emerald-500 bg-[#d9fdd3] text-zinc-900 dark:bg-emerald-950/60 dark:text-emerald-50'
                                            }`}
                                        >
                                            <div className="whitespace-pre-wrap">{msg.text}</div>
                                            {!isUser && msg.buttons && msg.buttons.length > 0 && (
                                                <div className="mt-2.5 space-y-1.5 border-t border-emerald-600/15 pt-2">
                                                    {msg.buttons.map((btn) => (
                                                        <button
                                                            key={btn.id}
                                                            type="button"
                                                            disabled={isSimulating}
                                                            onClick={() => handleSimulateMessage(btn.title)}
                                                            className="flex w-full items-center justify-center rounded-xl border border-emerald-600/30 bg-white/95 px-3 py-2 text-center text-xs font-bold text-emerald-700 shadow-sm transition hover:border-emerald-600 hover:bg-emerald-50 active:scale-98 dark:border-emerald-500/30 dark:bg-zinc-900 dark:text-emerald-300 dark:hover:bg-zinc-800"
                                                        >
                                                            {btn.title}
                                                        </button>
                                                    ))}
                                                </div>
                                            )}
                                        </div>
                                    </div>
                                );
                            })}
                        </div>

                        {/* Input Area */}
                        <form
                            onSubmit={(e) => {
                                e.preventDefault();
                                handleSimulateMessage(simulatorInput);
                            }}
                            className="flex items-center gap-2 border-t bg-white p-3 dark:bg-zinc-900"
                        >
                            <Button
                                type="submit"
                                disabled={
                                    isSimulating || !simulatorInput.trim()
                                }
                                className="h-9 rounded-full bg-[#075e54] px-4 text-xs text-white hover:bg-[#128c7e]"
                            >
                                {isSimulating ? 'Mengirim...' : 'Kirim'}
                            </Button>
                            <Input
                                value={simulatorInput}
                                onChange={(e) =>
                                    setSimulatorInput(e.target.value)
                                }
                                disabled={isSimulating}
                                className="h-9 flex-1 bg-zinc-50 text-left text-xs dark:bg-zinc-800"
                                placeholder="Ketik pesan uji coba..."
                            />
                        </form>
                    </div>
                )}

                <ReactFlow
                    className="h-full w-full pt-16"
                    edges={edges}
                    fitView
                    maxZoom={1.3}
                    minZoom={0.35}
                    nodes={nodes}
                    nodeTypes={nodeTypes}
                    onInit={(instance) => {
                        reactFlowInstanceRef.current = instance;
                    }}
                    onEdgesChange={onEdgesChange}
                    onConnect={onConnect}
                    onNodeClick={(_, node) => {
                        const actionIndex = node.data.actionIndex;

                        if (typeof actionIndex === 'number') {
                            setSelectedActionIndex(actionIndex);
                        }
                    }}
                    onNodesChange={onNodesChange}
                    onDragOver={(event) => {
                        event.preventDefault();
                        event.dataTransfer.dropEffect = 'move';
                    }}
                    onDrop={(event) => {
                        event.preventDefault();
                        const type = event.dataTransfer.getData(
                            'application/reactflow',
                        ) as ActionType;
                        if (!type || !reactFlowInstanceRef.current) {
                            return;
                        }

                        const flowPos =
                            reactFlowInstanceRef.current.screenToFlowPosition({
                                x: event.clientX,
                                y: event.clientY,
                            });

                        handleAddAction(type, {
                            x: Math.round(flowPos.x - 130),
                            y: Math.round(flowPos.y - 60),
                        });
                    }}
                >
                    <Background color="#94a3b8" gap={24} size={1.2} />
                    <Controls position="bottom-left" showInteractive={false} />
                </ReactFlow>
            </main>
        </div>
    );
}
