'use client';

import React, { useCallback, useEffect, useState } from 'react';
import { Button, Space, Typography } from 'antd';
import {
    ReactFlow,
    Background,
    Controls,
    MiniMap,
    addEdge,
    useEdgesState,
    useNodesState,
    type Connection,
    type Edge,
    type Node,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import { useIsMobile } from '@/hooks/useIsMobile';
import type { CasoUsoGrafo } from './types';

type Variant = 'uml' | 'atividade';
type EdgeKind = 'fluxo' | 'include' | 'extend' | 'associacao';

type Props = {
    grafo: CasoUsoGrafo;
    readOnly?: boolean;
    variant?: Variant;
    onSave: (grafo: CasoUsoGrafo) => void;
};

function toGrafo(nodes: Node[], edges: Edge[]): CasoUsoGrafo {
    return {
        nodes: nodes.map((n) => ({
            id: n.id,
            type: n.type,
            position: n.position,
            data: (n.data ?? {}) as CasoUsoGrafo['nodes'][number]['data'],
        })),
        edges: edges.map((e) => ({
            id: e.id,
            source: e.source,
            target: e.target,
            type: e.type,
        })),
    };
}

export function CasoUsoFlowCanvas({ grafo, readOnly, variant = 'atividade', onSave }: Props) {
    const isMobile = useIsMobile();
    const [edgeKind, setEdgeKind] = useState<EdgeKind>(variant === 'uml' ? 'associacao' : 'fluxo');
    const [nodes, setNodes, onNodesChange] = useNodesState((grafo.nodes ?? []) as Node[]);
    const [edges, setEdges, onEdgesChange] = useEdgesState((grafo.edges ?? []) as Edge[]);

    useEffect(() => {
        setNodes((grafo.nodes ?? []) as Node[]);
        setEdges((grafo.edges ?? []) as Edge[]);
    }, [grafo, setEdges, setNodes]);

    const persist = useCallback(
        (n = nodes, e = edges) => {
            if (readOnly) {
                return;
            }
            onSave(toGrafo(n, e));
        },
        [edges, nodes, onSave, readOnly],
    );

    const onConnect = useCallback(
        (connection: Connection) => {
            if (readOnly) {
                return;
            }
            setEdges((eds) => {
                const next = addEdge({ ...connection, type: edgeKind }, eds);
                queueMicrotask(() => persist(nodes, next));
                return next;
            });
        },
        [edgeKind, nodes, persist, readOnly, setEdges],
    );

    const addNode = (type: string, label: string) => {
        if (readOnly) {
            return;
        }
        const id = `${type}-${Date.now()}`;
        const next = [
            ...nodes,
            {
                id,
                type,
                position: { x: 80 + nodes.length * 24, y: 80 + nodes.length * 24 },
                data: { label },
            } as Node,
        ];
        setNodes(next);
        persist(next, edges);
    };

    if (isMobile) {
        return (
            <Typography.Paragraph>
                O desenho do diagrama é feito no computador. Nesta tela você consulta o fluxo; use a aba Fluxo para
                editar os passos.
            </Typography.Paragraph>
        );
    }

    return (
        <div>
            {!readOnly ? (
                <Space wrap style={{ marginBottom: 12 }}>
                    {variant === 'uml' ? (
                        <>
                            <Button size="small" onClick={() => addNode('ator', 'Ator')}>
                                Ator
                            </Button>
                            <Button size="small" onClick={() => addNode('caso_uso', 'Caso de uso')}>
                                Caso de uso
                            </Button>
                            <Button size="small" onClick={() => addNode('sistema', 'Sistema')}>
                                Sistema
                            </Button>
                            <Button size="small" onClick={() => addNode('nota', 'Nota')}>
                                Nota
                            </Button>
                            <Typography.Text type="secondary">Ligação:</Typography.Text>
                            {(['associacao', 'include', 'extend'] as const).map((k) => (
                                <Button
                                    key={k}
                                    size="small"
                                    type={edgeKind === k ? 'primary' : 'default'}
                                    onClick={() => setEdgeKind(k)}
                                >
                                    {k === 'associacao' ? 'Associação' : k === 'include' ? 'Include' : 'Extend'}
                                </Button>
                            ))}
                        </>
                    ) : (
                        <>
                            <Button size="small" onClick={() => addNode('passo', 'Passo')}>
                                Passo
                            </Button>
                            <Button size="small" onClick={() => addNode('decisao', 'Decisão')}>
                                Decisão
                            </Button>
                            <Button size="small" onClick={() => addNode('inicio', 'Início')}>
                                Início
                            </Button>
                            <Button size="small" onClick={() => addNode('fim', 'Fim')}>
                                Fim
                            </Button>
                        </>
                    )}
                    <Button size="small" type="primary" onClick={() => persist()}>
                        Salvar diagrama
                    </Button>
                </Space>
            ) : null}
            <div style={{ width: '100%', height: 480, border: '1px solid var(--border)', borderRadius: 8 }}>
                <ReactFlow
                    nodes={nodes}
                    edges={edges}
                    onNodesChange={onNodesChange}
                    onEdgesChange={onEdgesChange}
                    onConnect={onConnect}
                    onNodeDragStop={() => persist()}
                    fitView
                    nodesDraggable={!readOnly}
                    nodesConnectable={!readOnly}
                    elementsSelectable={!readOnly}
                >
                    <Background />
                    <Controls />
                    <MiniMap />
                </ReactFlow>
            </div>
        </div>
    );
}
