/**
 * FlowEditorModal
 * npm install @xyflow/react
 */

import React, { useCallback, useEffect, useState } from 'react';
import {
    ReactFlow,
    ReactFlowProvider,
    Background,
    Controls,
    addEdge,
    useNodesState,
    useEdgesState,
    useReactFlow,
    BackgroundVariant,
    Handle,
    Position,
    MarkerType,
    type Node,
    type Edge,
    type Connection,
    type NodeTypes,
    type NodeProps,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { X, Save, Clock, Cable, Pause, Play, Pencil, GitBranch, Layers } from 'lucide-react';
import { Link } from '@inertiajs/react';

// ── tipos ─────────────────────────────────────────────────────────────────────

interface ActivityOrigDest {
    id: number;
    name: string;
    stream_position: number;
    cron_time: number;
    activity_orig_dest_connections?: {
        enabled: boolean;
        filter?: string;
        conditions?: string;
        connection_data?: { name: string };
    };
}

export interface MultiFlowData {
    id: number;
    name: string;
    cron_start?: string;
    cron_end?: string;
    activity_origs_dests: ActivityOrigDest[];
}

interface FlowEditorModalProps {
    open: boolean;
    onClose: () => void;
    activityFlow: MultiFlowData;
    /** Quando passado com mais de 1 item, renderiza todos os fluxos juntos no canvas */
    allActivityFlows?: MultiFlowData[];
    connections: any[];
    flowName?: string;
    onSave?: (nodes: Node[], edges: Edge[]) => void;
}

// ── cores ─────────────────────────────────────────────────────────────────────

const EDGE_COLOR = '#3B82F6';

const EDGE_DEFAULTS = {
    type:      'smoothstep' as const,
    style:     { stroke: EDGE_COLOR, strokeWidth: 2.5 },
    markerEnd: {
        type:   MarkerType.ArrowClosed,
        color:  EDGE_COLOR,
        width:  18,
        height: 18,
    },
};

// ── nó de atividade (existente) ───────────────────────────────────────────────

function ActivityNode({ data, selected }: NodeProps) {
    const d = data as any;
    const isActive = d.enabled !== false;

    const portStyle: React.CSSProperties = {
        width: 12, height: 12,
        borderRadius: '50%',
        border: `2px solid ${EDGE_COLOR}`,
        background: isActive ? EDGE_COLOR : '#F87171',
        cursor: 'crosshair',
        zIndex: 10,
    };

    return (
        <div style={{ width: 186 }}>
            <Handle type="target" position={Position.Left}  style={portStyle} />

            <div style={{
                borderRadius: 12,
                border: `2px solid ${selected ? EDGE_COLOR : isActive ? '#E2E8F0' : '#FECACA'}`,
                background: isActive ? '#ffffff' : '#FFF5F5',
                boxShadow: selected
                    ? `0 0 0 3px rgba(59,130,246,.18), 0 2px 8px rgba(0,0,0,.08)`
                    : '0 1px 5px rgba(0,0,0,.07)',
                transition: 'border-color .12s, box-shadow .12s',
            }}>
                <div style={{ padding: '9px 11px 5px', display: 'flex', alignItems: 'flex-start', gap: 7 }}>
                    <div style={{
                        width: 19, height: 19, borderRadius: '50%',
                        background: '#F1F5F9', border: '1px solid #E2E8F0',
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                        fontSize: 9, fontWeight: 800, color: '#64748B',
                        flexShrink: 0, marginTop: 1,
                    }}>
                        {d.position}
                    </div>
                    <span style={{ flex: 1, fontSize: 12, fontWeight: 700, color: '#1E293B', lineHeight: 1.3 }}>
                        {d.label}
                    </span>
                </div>

                <div style={{ padding: '0 11px 9px', display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                    {d.connection && (
                        <span style={{
                            display: 'inline-flex', alignItems: 'center', gap: 3,
                            fontSize: 10, color: '#64748B',
                            background: '#F8FAFC', border: '1px solid #E2E8F0',
                            borderRadius: 5, padding: '2px 6px',
                            maxWidth: 120, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                        }}>
                            <Cable size={9} strokeWidth={2.5} style={{ flexShrink: 0 }} />
                            {d.connection}
                        </span>
                    )}
                    <span style={{
                        display: 'inline-flex', alignItems: 'center', gap: 3,
                        fontSize: 10, color: '#64748B',
                        background: '#F8FAFC', border: '1px solid #E2E8F0',
                        borderRadius: 5, padding: '2px 6px',
                    }}>
                        <Clock size={9} strokeWidth={2.5} style={{ flexShrink: 0 }} />
                        {d.cron} min
                    </span>
                    <span style={{
                        fontSize: 10, fontWeight: 700,
                        padding: '2px 7px', borderRadius: 20,
                        background: isActive ? '#D1FAE5' : '#FEE2E2',
                        color:      isActive ? '#065F46' : '#991B1B',
                    }}>
                        {isActive ? 'ativo' : 'pausado'}
                    </span>
                </div>
            </div>

            <Handle type="source" position={Position.Right} style={{ ...portStyle, background: EDGE_COLOR }} />
        </div>
    );
}

// ── nó separador de fluxo (novo) ──────────────────────────────────────────────

// Paleta de cores para distinguir visualmente os fluxos
const FLOW_COLORS = [
    { bg: '#EFF6FF', border: '#BFDBFE', icon: '#3B82F6', text: '#1D4ED8' }, // azul  (pai)
    { bg: '#F0FDF4', border: '#BBF7D0', icon: '#22C55E', text: '#15803D' }, // verde (sub 1)
    { bg: '#FFF7ED', border: '#FED7AA', icon: '#F97316', text: '#C2410C' }, // laranja (sub 2)
    { bg: '#FAF5FF', border: '#E9D5FF', icon: '#A855F7', text: '#7E22CE' }, // roxo (sub 3)
    { bg: '#FFF1F2', border: '#FECDD3', icon: '#F43F5E', text: '#BE123C' }, // rosa (sub 4)
];

function FlowLabelNode({ data }: NodeProps) {
    const d = data as any;
    const palette = FLOW_COLORS[d.colorIndex ?? 0] ?? FLOW_COLORS[0];

    return (
        <div
            style={{
                background: palette.bg,
                border: `1.5px solid ${palette.border}`,
                borderRadius: 10,
                padding: '7px 14px',
                display: 'flex',
                alignItems: 'center',
                gap: 8,
                minWidth: 220,
                pointerEvents: 'none',
                userSelect: 'none',
                boxShadow: '0 1px 4px rgba(0,0,0,0.06)',
            }}
        >
            <GitBranch size={13} style={{ color: palette.icon, flexShrink: 0 }} strokeWidth={2.5} />
            <span style={{ fontSize: 12, fontWeight: 700, color: palette.text, lineHeight: 1 }}>
                {d.label}
            </span>
            {d.isSubFlow && (
                <span style={{
                    fontSize: 9, fontWeight: 700, color: palette.icon,
                    background: palette.border, borderRadius: 20,
                    padding: '2px 7px', flexShrink: 0,
                }}>
                    subfluxo
                </span>
            )}
            {d.cronStart && (
                <span style={{ fontSize: 10, color: '#64748B', flexShrink: 0 }}>
                    {d.cronStart}–{d.cronEnd}
                </span>
            )}
            <span style={{ fontSize: 10, color: '#94A3B8', flexShrink: 0 }}>
                {d.activityCount} {d.activityCount === 1 ? 'atividade' : 'atividades'}
            </span>
        </div>
    );
}

// ── conversão de dados → nodes + edges ───────────────────────────────────────

const W = 186, H = 88, GAP_X = 90, GAP_Y = 80, COLS = 4;
const HEADER_H      = 40;
const HEADER_PAD    = 14;
const FLOW_GAP      = 56;

/** Converte um único fluxo (comportamento original) */
function aodToFlow(aods: ActivityOrigDest[]): { nodes: Node[]; edges: Edge[] } {
    const sorted = [...aods].sort((a, b) => (a.stream_position ?? 0) - (b.stream_position ?? 0));

    const nodes: Node[] = sorted.map((aod, idx) => ({
        id:       String(aod.id),
        type:     'activity',
        position: {
            x: (idx % COLS) * (W + GAP_X) + 40,
            y: Math.floor(idx / COLS) * (H + GAP_Y) + 40,
        },
        data: {
            label:      aod.name,
            position:   aod.stream_position,
            cron:       aod.cron_time,
            connection: aod.activity_orig_dest_connections?.connection_data?.name ?? '',
            enabled:    aod.activity_orig_dest_connections?.enabled ?? true,
            filter:     aod.activity_orig_dest_connections?.filter ?? '',
            conditions: aod.activity_orig_dest_connections?.conditions ?? '',
            aodId:      aod.id,
        },
    }));

    const edges: Edge[] = sorted.slice(0, -1).map((aod, idx) => ({
        id:     `e-${aod.id}-${sorted[idx + 1].id}`,
        source: String(aod.id),
        target: String(sorted[idx + 1].id),
        ...EDGE_DEFAULTS,
    }));

    return { nodes, edges };
}

/** Converte múltiplos fluxos em um único grafo com separadores visuais */
function multiFlowsToGraph(flows: MultiFlowData[]): { nodes: Node[]; edges: Edge[] } {
    const allNodes: Node[] = [];
    const allEdges: Edge[] = [];

    let currentY = 30;

    flows.forEach((flow, flowIdx) => {
        const sorted = [...(flow.activity_origs_dests ?? [])].sort(
            (a, b) => (a.stream_position ?? 0) - (b.stream_position ?? 0)
        );

        // Cabeçalho separador do fluxo
        allNodes.push({
            id:   `flow-label-${flow.id}`,
            type: 'flow-label',
            position: { x: 40, y: currentY },
            data: {
                label:         flow.name,
                cronStart:     flow.cron_start,
                cronEnd:       flow.cron_end,
                colorIndex:    flowIdx,
                isSubFlow:     flowIdx > 0,
                activityCount: sorted.length,
            },
            selectable: false,
            draggable:  false,
        } as Node);

        const activitiesStartY = currentY + HEADER_H + HEADER_PAD;

        // Nós de atividade
        sorted.forEach((aod, idx) => {
            allNodes.push({
                id:   String(aod.id),
                type: 'activity',
                position: {
                    x: (idx % COLS) * (W + GAP_X) + 40,
                    y: activitiesStartY + Math.floor(idx / COLS) * (H + GAP_Y),
                },
                data: {
                    label:      aod.name,
                    position:   aod.stream_position,
                    cron:       aod.cron_time,
                    connection: aod.activity_orig_dest_connections?.connection_data?.name ?? '',
                    enabled:    aod.activity_orig_dest_connections?.enabled ?? true,
                    filter:     aod.activity_orig_dest_connections?.filter ?? '',
                    conditions: aod.activity_orig_dest_connections?.conditions ?? '',
                    aodId:      aod.id,
                },
            });
        });

        // Arestas dentro do fluxo
        sorted.slice(0, -1).forEach((aod, idx) => {
            allEdges.push({
                id:     `e-${aod.id}-${sorted[idx + 1].id}`,
                source: String(aod.id),
                target: String(sorted[idx + 1].id),
                ...EDGE_DEFAULTS,
            });
        });

        // Avança Y para o próximo fluxo
        const numRows   = sorted.length > 0 ? Math.ceil(sorted.length / COLS) : 1;
        const contentH  = numRows * H + Math.max(0, numRows - 1) * GAP_Y;
        currentY        = activitiesStartY + contentH + FLOW_GAP;
    });

    return { nodes: allNodes, edges: allEdges };
}

// ── painel de detalhes (sidebar direita) ──────────────────────────────────────

function DetailPanel({
    node,
    onToggleActive,
}: {
    node: Node | null;
    onToggleActive: (nodeId: string, current: boolean) => void;
}) {
    if (!node) {
        return (
            <div style={{
                width: 260, flexShrink: 0,
                borderLeft: '1px solid #E2E8F0',
                background: '#fff',
                display: 'flex', flexDirection: 'column',
                alignItems: 'center', justifyContent: 'center',
                gap: 8, color: '#94A3B8',
            }}>
                <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.2" opacity={0.35}>
                    <rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/>
                    <rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/>
                </svg>
                <span style={{ fontSize: 12 }}>Clique num nó para ver detalhes</span>
            </div>
        );
    }

    const d = node.data as any;
    const isActive = d.enabled !== false;

    const Field = ({ label, value, mono = false }: { label: string; value: string; mono?: boolean }) => (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
            <span style={{ fontSize: 9, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.07em', color: '#94A3B8' }}>
                {label}
            </span>
            <span style={{
                fontSize: mono ? 11 : 12, fontWeight: mono ? 400 : 500, color: '#1E293B',
                ...(mono ? {
                    fontFamily: 'monospace',
                    background: '#F8FAFC', border: '1px solid #E2E8F0',
                    borderRadius: 5, padding: '3px 7px',
                } : {}),
            }}>
                {value || '—'}
            </span>
        </div>
    );

    return (
        <div style={{
            width: 260, flexShrink: 0,
            borderLeft: '1px solid #E2E8F0',
            background: '#fff',
            display: 'flex', flexDirection: 'column',
            overflow: 'hidden',
        }}>
            <div style={{ padding: '13px 14px 10px', borderBottom: '1px solid #E2E8F0', flexShrink: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 700, color: '#0F172A', marginBottom: 7, lineHeight: 1.3 }}>
                    {d.label}
                </div>
                <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap' }}>
                    <span style={{
                        fontSize: 10, fontWeight: 700, padding: '2px 8px', borderRadius: 20,
                        background: isActive ? '#D1FAE5' : '#FEE2E2',
                        color:      isActive ? '#065F46' : '#991B1B',
                    }}>
                        {isActive ? 'ativo' : 'pausado'}
                    </span>
                    <span style={{
                        fontSize: 10, color: '#64748B',
                        background: '#F8FAFC', border: '1px solid #E2E8F0',
                        borderRadius: 5, padding: '2px 7px',
                    }}>
                        posição {d.position}
                    </span>
                </div>
            </div>

            <div style={{ flex: 1, overflowY: 'auto', padding: '12px 14px', display: 'flex', flexDirection: 'column', gap: 10 }}>
                <Field label="Conexão"   value={d.connection} />
                <div style={{ height: 1, background: '#F1F5F9' }} />
                <Field label="Cron"      value={`${d.cron} min`} />
                <Field label="Filtro"    value={d.filter}     mono />
                <Field label="Condições" value={d.conditions} mono />
                <div style={{ height: 1, background: '#F1F5F9' }} />
                <Field label="ID"        value={String(d.aodId ?? node.id)} mono />
            </div>

            <div style={{
                padding: '10px 14px', borderTop: '1px solid #E2E8F0',
                display: 'flex', flexDirection: 'column', gap: 6, flexShrink: 0,
            }}>
                <button
                    type="button"
                    onClick={() => onToggleActive(node.id, isActive)}
                    style={{
                        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
                        fontSize: 11, fontWeight: 700,
                        padding: '6px 10px', borderRadius: 7, cursor: 'pointer',
                        border: `1px solid ${isActive ? '#FECACA' : '#A7F3D0'}`,
                        background: isActive ? '#FFF5F5' : '#ECFDF5',
                        color:      isActive ? '#B91C1C' : '#065F46',
                    }}
                >
                    {isActive
                        ? <><Pause size={11} strokeWidth={2.5} /> Pausar</>
                        : <><Play  size={11} strokeWidth={2.5} /> Ativar</>
                    }
                </button>

                {d.aodId && (
                    <Link
                        href={route('integracoes.edit', { id: d.aodId })}
                        style={{
                            display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 5,
                            fontSize: 11, fontWeight: 600, textDecoration: 'none',
                            padding: '6px 10px', borderRadius: 7, cursor: 'pointer',
                            border: '1px solid #BFDBFE',
                            background: '#EFF6FF',
                            color: '#1D4ED8',
                        }}
                    >
                        <Pencil size={11} strokeWidth={2.5} />
                        Editar atividade
                    </Link>
                )}
            </div>
        </div>
    );
}

// ── editor ────────────────────────────────────────────────────────────────────

const nodeTypes: NodeTypes = {
    activity:   ActivityNode,
    'flow-label': FlowLabelNode,
};

function FlowEditor({
    activityFlow,
    allActivityFlows,
    onSave,
    onClose,
    flowName,
}: {
    activityFlow: MultiFlowData;
    allActivityFlows?: MultiFlowData[];
    onSave?: FlowEditorModalProps['onSave'];
    onClose: () => void;
    flowName?: string;
}) {
    const { fitView } = useReactFlow();

    // Usa visualização combinada se houver múltiplos fluxos
    const isMultiFlow = (allActivityFlows?.length ?? 0) > 1;

    const { nodes: initNodes, edges: initEdges } = isMultiFlow
        ? multiFlowsToGraph(allActivityFlows!)
        : aodToFlow(activityFlow.activity_origs_dests ?? []);

    const [nodes, setNodes, onNodesChange] = useNodesState(initNodes);
    const [edges, setEdges, onEdgesChange] = useEdgesState(initEdges);
    const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);

    useEffect(() => {
        setTimeout(() => fitView({ padding: 0.12, duration: 300 }), 100);
    }, []);

    const onConnect = useCallback(
        (connection: Connection) => setEdges(eds => addEdge({ ...connection, ...EDGE_DEFAULTS }, eds)),
        [setEdges]
    );

    const onNodeClick = useCallback((_: React.MouseEvent, node: Node) => {
        // Ignora clique em cabeçalhos de fluxo
        if (node.type === 'flow-label') return;
        setSelectedNodeId(prev => prev === node.id ? null : node.id);
    }, []);

    const onPaneClick = useCallback(() => {
        setSelectedNodeId(null);
    }, []);

    const handleToggleActive = useCallback((nodeId: string, currentActive: boolean) => {
        setNodes(nds =>
            nds.map(n =>
                n.id === nodeId
                    ? { ...n, data: { ...n.data, enabled: !currentActive } }
                    : n
            )
        );
    }, [setNodes]);

    const selectedNode = nodes.find(n => n.id === selectedNodeId) ?? null;

    // Conta apenas nós de atividade (exclui os cabeçalhos)
    const activityNodeCount = nodes.filter(n => n.type !== 'flow-label').length;

    return (
        <div style={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>

            {/* header */}
            <div className="flex items-center justify-between px-5 py-3.5 border-b border-border bg-card flex-shrink-0 gap-3">
                <div className="flex items-center gap-2.5 min-w-0">
                    <span className="bg-blue-50 dark:bg-blue-950 rounded-lg p-1.5 flex items-center flex-shrink-0">
                        {isMultiFlow
                            ? <Layers  size={15} className="text-blue-600 dark:text-blue-400" strokeWidth={2.2} />
                            : <GitBranch size={15} className="text-blue-600 dark:text-blue-400" strokeWidth={2.2} />
                        }
                    </span>
                    <span className="text-sm font-semibold text-foreground tracking-tight truncate">
                        {flowName ?? activityFlow.name}
                    </span>
                    {isMultiFlow && (
                        <span className="flex-shrink-0 inline-flex items-center gap-1 text-[10px] font-semibold text-blue-700 dark:text-blue-400 bg-blue-50 dark:bg-blue-950 border border-blue-200 dark:border-blue-800 rounded-full px-2 py-0.5">
                            <Layers size={9} strokeWidth={2.5} />
                            {allActivityFlows!.length} fluxos
                        </span>
                    )}
                    <span className="flex-shrink-0 text-[10px] text-muted-foreground bg-muted border border-border rounded-full px-2 py-0.5">
                        {activityNodeCount} {activityNodeCount === 1 ? 'atividade' : 'atividades'}
                    </span>
                    {!isMultiFlow && activityFlow.cron_start && (
                        <span className="flex-shrink-0 flex items-center gap-1 text-[11px] text-muted-foreground">
                            <Clock size={11} strokeWidth={2} />
                            {activityFlow.cron_start} – {activityFlow.cron_end}
                        </span>
                    )}
                </div>

                <div className="flex items-center gap-2 flex-shrink-0">
                    <span className="text-[11px] text-muted-foreground hidden sm:block">
                        Arraste nós · conecte as portas · Delete remove
                    </span>
                    <button
                        type="button"
                        onClick={() => { onSave?.(nodes, edges); onClose(); }}
                        className="inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-1.5 rounded-lg bg-foreground text-background hover:opacity-90 transition-opacity cursor-pointer"
                    >
                        <Save size={12} strokeWidth={2.5} />
                        Salvar fluxo
                    </button>
                    <button
                        type="button"
                        onClick={onClose}
                        className="w-8 h-8 rounded-lg border border-border bg-card flex items-center justify-center hover:bg-muted transition-colors cursor-pointer"
                    >
                        <X size={14} strokeWidth={2} className="text-muted-foreground" />
                    </button>
                </div>
            </div>

            {/* canvas + painel de detalhes */}
            <div style={{ display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }}>
                <div style={{ flex: 1, minWidth: 0, height: '100%', position: 'relative', background: '#F8FAFC' }}>
                    <ReactFlow
                        nodes={nodes}
                        edges={edges}
                        nodeTypes={nodeTypes}
                        onNodesChange={onNodesChange}
                        onEdgesChange={onEdgesChange}
                        onConnect={onConnect}
                        onNodeClick={onNodeClick}
                        onPaneClick={onPaneClick}
                        fitView
                        fitViewOptions={{ padding: 0.12 }}
                        minZoom={0.1}
                        deleteKeyCode="Delete"
                        snapToGrid
                        snapGrid={[16, 16]}
                        defaultEdgeOptions={EDGE_DEFAULTS}
                        proOptions={{ hideAttribution: true }}
                        panOnDrag
                        panOnScroll={false}
                        zoomOnScroll
                        zoomOnPinch
                        zoomOnDoubleClick={false}
                        nodesDraggable
                        nodesConnectable
                        nodesFocusable
                        edgesFocusable={false}
                        style={{ width: '100%', height: '100%' }}
                    >
                        <Background variant={BackgroundVariant.Dots} gap={22} size={1.2} color="#CBD5E1" />
                        <Controls
                            showInteractive={false}
                            style={{
                                borderRadius: 8,
                                border: '1px solid #E2E8F0',
                                boxShadow: 'none',
                                overflow: 'hidden',
                                background: '#fff',
                            }}
                        />
                    </ReactFlow>
                </div>

                <DetailPanel node={selectedNode} onToggleActive={handleToggleActive} />
            </div>
        </div>
    );
}

// ── modal wrapper ─────────────────────────────────────────────────────────────

export function FlowEditorModal({
    open,
    onClose,
    activityFlow,
    allActivityFlows,
    connections,
    flowName,
    onSave,
}: FlowEditorModalProps) {
    if (!open) return null;

    return (
        <div
            className="fixed inset-0 z-50 flex items-center justify-center p-2 bg-black/80"
            onClick={e => { if (e.target === e.currentTarget) onClose(); }}
        >
            <div className="w-full bg-card border border-border rounded-2xl shadow-2xl overflow-hidden flex flex-col"
                style={{ maxWidth: 'min(1600px, 98vw)', height: '95vh', minHeight: 520 }}
            >
                <ReactFlowProvider>
                    <FlowEditor
                        activityFlow={activityFlow}
                        allActivityFlows={allActivityFlows}
                        onSave={onSave}
                        onClose={onClose}
                        flowName={flowName}
                    />
                </ReactFlowProvider>
            </div>
        </div>
    );
}
