import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import {
  Button,
  Card,
  Input,
  message,
  Modal,
  Segmented,
  Select,
  Space,
  Spin,
  Tag,
  Typography,
} from 'antd';
import {
  ArrowLeftOutlined,
  EditOutlined,
  RobotOutlined,
  RocketOutlined,
  SaveOutlined,
} from '@ant-design/icons';
import { useNavigate, useParams } from 'react-router-dom';
import { customRequest } from 'helpers/http';
import { FlowRenderer } from './components/FlowRenderer';
import { NodePropertyPanel } from './components/NodePropertyPanel';
import { DslView, type DslViewHandle } from './components/DslView';
import { useWorkflowAgent } from './hooks/useWorkflowAgent';
import type {
  Workflow,
  WorkflowDSL,
  WorkflowNode,
  WorkflowNodeType,
  WorkflowVersion,
} from './types';

const { Title } = Typography;
const { TextArea } = Input;

const NEW_DRAFT_KEY = 'workflow_new_draft';
const EDIT_DRAFT_KEY = (id: string) => `workflow_draft_${id}`;
const isDev = import.meta.env.DEV;

export default function WorkflowEditorPage() {
  const { id } = useParams<{ id: string }>();
  const isNewMode = !id;
  const navigate = useNavigate();

  const [workflow, setWorkflow] = useState<Workflow | null>(null);
  const [versions, setVersions] = useState<WorkflowVersion[]>([]);
  const [nodeTypes, setNodeTypes] = useState<WorkflowNodeType[]>([]);
  const [loading, setLoading] = useState(!isNewMode);

  const [dsl, setDsl] = useState<WorkflowDSL | null>(null);
  const [currentVersion, setCurrentVersion] = useState<number | null>(null);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);

  const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
  const [viewMode, setViewMode] = useState<'canvas' | 'dsl'>('canvas');
  const dslViewRef = useRef<DslViewHandle>(null);

  // Title editing state
  const [title, setTitle] = useState(isNewMode ? 'Untitled Workflow' : '');
  const [editingTitle, setEditingTitle] = useState(false);
  const titleInputRef = useRef<any>(null);

  // Save name modal
  const [nameModalOpen, setNameModalOpen] = useState(false);
  const [saveName, setSaveName] = useState('');
  const [saving, setSaving] = useState(false);

  // AI generate modal
  const [aiModalOpen, setAiModalOpen] = useState(false);
  const [aiPromptText, setAiPromptText] = useState('');

  const nodeTypeMap = useMemo(() => {
    const map: Record<string, { category: string; icon: string }> = {};
    for (const nt of nodeTypes) {
      map[nt.type] = { category: nt.category, icon: nt.icon };
    }
    return map;
  }, [nodeTypes]);

  const selectedNode: WorkflowNode | null = useMemo(() => {
    if (!selectedNodeId || !dsl) return null;
    return dsl.nodes.find((n) => n.id === selectedNodeId) || null;
  }, [selectedNodeId, dsl]);

  const {
    generate,
    abort: abortAgent,
    loading: agentLoading,
    error: agentError,
  } = useWorkflowAgent({ nodeTypes });

  // --- Load logic ---
  useEffect(() => {
    // Load node types for both modes
    customRequest<WorkflowNodeType[]>('workflow-node-types', 'GET')
      .then(setNodeTypes)
      .catch(() => {});
  }, []);

  useEffect(() => {
    if (isNewMode) {
      // New mode: load from localStorage
      const saved = localStorage.getItem(NEW_DRAFT_KEY);
      if (saved) {
        try {
          const parsed = JSON.parse(saved);
          setDsl(parsed.dsl || null);
          setTitle(parsed.title || 'Untitled Workflow');
        } catch {
          localStorage.removeItem(NEW_DRAFT_KEY);
        }
      }
      return;
    }

    // Edit mode: load from DB
    setLoading(true);
    setHasUnsavedChanges(false);
    Promise.all([
      customRequest<Workflow>(`workflow/${id}`, 'GET'),
      customRequest<WorkflowVersion[]>(`workflow/${id}/versions`, 'GET'),
    ])
      .then(([wf, vers]) => {
        setWorkflow(wf);
        setVersions(vers);
        setTitle(wf.name);
        // DSL comes from findOne (includes full latest version with dsl field)
        // getVersions only returns metadata (no dsl) for the version selector
        const latestVersion = (wf as any).versions?.[0];
        if (latestVersion?.dsl) {
          setDsl(latestVersion.dsl);
          setCurrentVersion(latestVersion.version);
        }
      })
      .catch((e) => {
        message.error(e?.message ?? 'Failed to load workflow');
      })
      .finally(() => {
        setLoading(false);
      });
  }, [id, isNewMode]);

  // --- Edit buffer: write to localStorage on every change ---
  useEffect(() => {
    if (!hasUnsavedChanges) return;
    if (isNewMode) {
      localStorage.setItem(NEW_DRAFT_KEY, JSON.stringify({ dsl, title }));
    } else if (id && dsl) {
      localStorage.setItem(EDIT_DRAFT_KEY(id), JSON.stringify(dsl));
    }
  }, [dsl, title, hasUnsavedChanges, isNewMode, id]);

  // --- Canvas edit callback ---
  const handleDslChange = useCallback((newDsl: WorkflowDSL) => {
    setDsl(newDsl);
    setHasUnsavedChanges(true);
  }, []);

  // --- AI edit workflow ---
  const handlePromptSubmit = useCallback(
    async (promptText: string) => {
      if (!promptText.trim()) return;
      const result = await generate({
        action: dsl ? 'edit_workflow' : 'create',
        prompt: promptText.trim(),
        currentDsl: dsl || undefined,
      });
      if (result && 'dsl' in result) {
        setDsl(result.dsl);
        setHasUnsavedChanges(true);
        message.success(result.changeSummary || 'Workflow updated');
      }
    },
    [dsl, generate],
  );

  // --- AI edit single node ---
  const handleNodeAiEdit = useCallback(
    async (nodeId: string, nodePrompt: string) => {
      if (!dsl) return;
      const result = await generate({
        action: 'edit_node',
        prompt: nodePrompt,
        currentDsl: dsl,
        targetNodeId: nodeId,
      });
      if (result && 'dsl' in result) {
        setDsl(result.dsl);
        setHasUnsavedChanges(true);
        message.success(result.changeSummary || 'Node updated');
      }
    },
    [dsl, generate],
  );

  // --- Node label change ---
  const handleNodeLabelChange = useCallback(
    (nodeId: string, newLabel: string) => {
      if (!dsl) return;
      const newNodes = dsl.nodes.map((n) =>
        n.id === nodeId ? { ...n, label: newLabel } : n,
      );
      setDsl({ ...dsl, nodes: newNodes });
      setHasUnsavedChanges(true);
    },
    [dsl],
  );

  // --- Delete node ---
  const handleNodeDelete = useCallback(
    (nodeId: string) => {
      if (!dsl) return;
      const newNodes = dsl.nodes.filter((n) => n.id !== nodeId);
      const newEdges = dsl.edges.filter(
        (e) => e.source !== nodeId && e.target !== nodeId,
      );
      setDsl({ nodes: newNodes, edges: newEdges });
      setHasUnsavedChanges(true);
      setSelectedNodeId(null);
    },
    [dsl],
  );

  // --- Node property save ---
  const handleNodePropertySave = useCallback(
    (
      nodeId: string,
      updates: {
        label?: string;
        config?: Record<string, any>;
        instanceRef?: WorkflowNode['instanceRef'] | null;
      },
    ) => {
      if (!dsl) return;
      const newNodes = dsl.nodes.map((n) => {
        if (n.id !== nodeId) return n;
        const updated = {
          ...n,
          label: updates.label ?? n.label,
          config: updates.config ?? n.config,
        };
        if (updates.instanceRef === null) {
          delete updated.instanceRef;
        } else if (updates.instanceRef !== undefined) {
          updated.instanceRef = updates.instanceRef;
        }
        return updated;
      });
      setDsl({ ...dsl, nodes: newNodes });
      setHasUnsavedChanges(true);
      message.success('节点属性已更新');
    },
    [dsl],
  );

  // --- Title editing ---
  function handleTitleEditStart() {
    setEditingTitle(true);
    setTimeout(() => titleInputRef.current?.focus(), 0);
  }

  function handleTitleEditEnd() {
    setEditingTitle(false);
    const trimmed = title.trim();
    if (!trimmed) {
      setTitle('Untitled Workflow');
    }
    setHasUnsavedChanges(true);
  }

  // --- Save logic ---
  async function handleSave() {
    if (!dsl) return;

    if (title === 'Untitled Workflow') {
      setSaveName('');
      setNameModalOpen(true);
      return;
    }

    await doSave(title);
  }

  async function handleNameModalOk() {
    const name = saveName.trim();
    if (!name) {
      message.warning('Please enter a workflow name');
      return;
    }
    setTitle(name);
    setNameModalOpen(false);
    await doSave(name);
  }

  async function doSave(name: string) {
    if (!dsl) return;
    setSaving(true);
    try {
      if (isNewMode) {
        // Create new workflow with DSL
        const wf = await customRequest<{ id: number }>('workflow', 'POST', {
          name,
          description: '',
          dsl,
        });
        localStorage.removeItem(NEW_DRAFT_KEY);
        message.success('Workflow saved!');
        navigate(`/admin/workflow/edit/${wf.id}`, { replace: true });
      } else {
        // Update existing: save draft
        // If name changed from DB, patch it
        if (workflow && name !== workflow.name) {
          await customRequest(`workflow/${id}`, 'PATCH', { name });
          setWorkflow((prev) => (prev ? { ...prev, name } : prev));
        }
        await customRequest(`workflow/${id}/save`, 'PATCH', { dsl });
        localStorage.removeItem(EDIT_DRAFT_KEY(id!));
        setHasUnsavedChanges(false);
        message.success('Saved!');
      }
    } catch (e: any) {
      message.error(e?.message ?? 'Save failed');
    } finally {
      setSaving(false);
    }
  }

  // --- Version selector ---
  async function handleSelectVersion(version: number) {
    if (!id) return;

    const dslDirty =
      viewMode === 'dsl' && (dslViewRef.current?.isDirty() ?? false);

    if (hasUnsavedChanges || dslDirty) {
      Modal.confirm({
        title: hasUnsavedChanges ? '未保存的修改' : 'DSL 有未应用的编辑',
        content: hasUnsavedChanges
          ? '当前有未保存的修改，切换版本将丢失这些更改。确定要继续吗？'
          : 'DSL 视图中有未应用到画布的编辑，切换版本将丢弃这些内容。确定要继续吗？',
        okText: '确定切换',
        cancelText: '取消',
        onOk: () => doLoadVersion(version),
      });
      return;
    }

    await doLoadVersion(version);
  }

  async function doLoadVersion(version: number) {
    if (!id) return;
    try {
      const v = await customRequest<WorkflowVersion>(
        `workflow/${id}/versions/${version}`,
        'GET',
      );
      setDsl(v.dsl);
      setCurrentVersion(v.version);
      setHasUnsavedChanges(false);
      setSelectedNodeId(null);
      localStorage.removeItem(EDIT_DRAFT_KEY(id));
    } catch (e: any) {
      message.error(e?.message ?? 'Failed to load version');
    }
  }

  function handleNodeClick(nodeId: string) {
    setSelectedNodeId(nodeId || null);
  }

  function handleViewModeChange(next: 'canvas' | 'dsl') {
    if (next === 'canvas' && viewMode === 'dsl') {
      // 切回画布前自动应用 textarea 中的 DSL；校验失败则阻止切换
      const success = dslViewRef.current?.apply() ?? true;
      if (!success) {
        // DslView 已显示内联 Alert，无需额外提示
        return;
      }
    }
    setViewMode(next);
  }

  function handleOpenAiModal() {
    const hasExistingWorkflow = !!(dsl && dsl.nodes.length > 0);
    if (hasExistingWorkflow) {
      Modal.confirm({
        title: '覆盖现有工作流',
        content:
          '当前已有工作流内容，AI 自动生成将覆盖现有内容。确定要继续吗？',
        okText: '确定继续',
        cancelText: '取消',
        onOk: () => setAiModalOpen(true),
      });
      return;
    }
    setAiModalOpen(true);
  }

  function handleDslApply(newDsl: WorkflowDSL) {
    setDsl(newDsl);
    setHasUnsavedChanges(true);
    setSelectedNodeId(null);
  }

  if (loading) {
    return (
      <div
        style={{
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
          height: '100vh',
        }}
      >
        <Spin size="large" />
      </div>
    );
  }

  return (
    <div
      style={{
        height: 'calc(100vh - 96px)',
        display: 'flex',
        flexDirection: 'column',
        background: '#f0f2f5',
        overflow: 'hidden',
      }}
    >
      {/* Header */}
      <Card style={{ marginBottom: 16, flexShrink: 0 }}>
        <div
          style={{
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
          }}
        >
          <Space>
            <Button
              type="text"
              icon={<ArrowLeftOutlined />}
              onClick={() => navigate('/admin/workflow')}
            ></Button>
            {editingTitle ? (
              <Input
                ref={titleInputRef}
                value={title}
                onChange={(e) => setTitle(e.target.value)}
                onBlur={handleTitleEditEnd}
                onPressEnter={handleTitleEditEnd}
                style={{ width: 260, fontWeight: 600, fontSize: 18 }}
              />
            ) : (
              <>
                <Title level={4} style={{ margin: 0 }}>
                  {title}
                </Title>
                <Button
                  type="text"
                  size="small"
                  icon={<EditOutlined />}
                  onClick={handleTitleEditStart}
                />
              </>
            )}
            {hasUnsavedChanges && <Tag color="orange">Unsaved</Tag>}
          </Space>
          <Space>
            {!isNewMode && versions.length > 0 && (
              <Select
                value={currentVersion}
                onChange={handleSelectVersion}
                style={{ width: 200 }}
                placeholder="选择版本"
                options={versions.map((v) => ({
                  label: `v${v.version} - ${v.changeSummary?.slice(0, 20) || 'Saved'}`,
                  value: v.version,
                }))}
              />
            )}
            {isDev && (
              <Button
                type="primary"
                icon={<RobotOutlined />}
                onClick={handleOpenAiModal}
              >
                AI自动生成
              </Button>
            )}
            <Button
              type="primary"
              icon={<SaveOutlined />}
              disabled={!dsl || !hasUnsavedChanges}
              loading={saving}
              onClick={handleSave}
            >
              Save
            </Button>
          </Space>
        </div>
      </Card>

      {/* View toggle row */}
      <div
        style={{
          marginBottom: 12,
          flexShrink: 0,
          display: 'flex',
          alignItems: 'center',
        }}
      >
        <Segmented
          value={viewMode}
          onChange={(v) => handleViewModeChange(v as 'canvas' | 'dsl')}
          options={[
            { label: '画布', value: 'canvas' },
            { label: 'DSL', value: 'dsl' },
          ]}
        />
      </div>

      {/* Main area: Flow + Property Panel */}
      <div
        style={{ flex: 1, display: 'flex', overflow: 'hidden', minHeight: 0 }}
      >
        {viewMode === 'canvas' ? (
          <>
            <div style={{ flex: 1, position: 'relative' }}>
              <FlowRenderer
                dsl={dsl}
                nodeTypeMap={nodeTypeMap}
                selectedNodeId={selectedNodeId}
                onNodeClick={handleNodeClick}
                onDslChange={handleDslChange}
              />
            </div>
            <NodePropertyPanel
              node={selectedNode}
              nodeTypes={nodeTypes}
              currentWorkflowId={id}
              onSave={handleNodePropertySave}
              onLabelChange={handleNodeLabelChange}
              onAiEdit={handleNodeAiEdit}
              onDelete={handleNodeDelete}
              onAbort={abortAgent}
              aiLoading={agentLoading}
            />
          </>
        ) : (
          <DslView ref={dslViewRef} dsl={dsl} onApply={handleDslApply} />
        )}
      </div>

      {/* Name modal for untitled workflows */}
      <Modal
        title="Save Workflow"
        open={nameModalOpen}
        onOk={handleNameModalOk}
        onCancel={() => setNameModalOpen(false)}
        okText="Save"
        okButtonProps={{ loading: saving }}
      >
        <div style={{ marginBottom: 8 }}>
          <Typography.Text strong>Workflow Name</Typography.Text>
        </div>
        <Input
          placeholder="Enter workflow name"
          value={saveName}
          onChange={(e) => setSaveName(e.target.value)}
          onPressEnter={handleNameModalOk}
          autoFocus
        />
      </Modal>

      {/* AI Generate modal */}
      <Modal
        title={null}
        open={aiModalOpen}
        onCancel={() => setAiModalOpen(false)}
        footer={null}
        width={520}
      >
        <div style={{ marginBottom: 12 }}>
          <Typography.Text style={{ fontSize: 14 }}>
            用自然语言描述整个工作流，AI将自动生成可视化的流程
          </Typography.Text>
        </div>
        <TextArea
          value={aiPromptText}
          onChange={(e) => setAiPromptText(e.target.value)}
          placeholder="Describe changes to this workflow..."
          autoSize={{ minRows: 6, maxRows: 12 }}
          onPressEnter={(e) => {
            if (e.ctrlKey && aiPromptText.trim()) {
              handlePromptSubmit(aiPromptText.trim());
              setAiPromptText('');
              setAiModalOpen(false);
            }
          }}
        />
        <Button
          type="primary"
          icon={<RocketOutlined />}
          onClick={() => {
            if (aiPromptText.trim()) {
              handlePromptSubmit(aiPromptText.trim());
              setAiPromptText('');
              setAiModalOpen(false);
            }
          }}
          disabled={!aiPromptText.trim()}
          loading={agentLoading}
          style={{ marginTop: 12 }}
          block
        >
          Generate Workflow
        </Button>
      </Modal>
    </div>
  );
}
