import { useEffect, useState, useRef, useCallback } from "react";
import { useParams, useNavigate } from "react-router-dom";
import {
  Layout, Button, Modal, Form, Input, Select, Upload,
  Space, message, Spin, Progress, Popconfirm, Card, Collapse,
} from "antd";
import {
  PlusOutlined, DeleteOutlined, EditOutlined, SaveOutlined,
  ArrowLeftOutlined, ThunderboltOutlined, DownloadOutlined,
  ExperimentOutlined, MenuFoldOutlined, MenuUnfoldOutlined,
} from "@ant-design/icons";
import { Editor } from "@tinymce/tinymce-react";
import type { Editor as TinyMCEEditor } from "tinymce";
import type { GenerationPoint, AIModel, GenerationTask } from "../types";
import * as templateApi from "../api/templates";
import * as pointApi from "../api/generationPoints";
import * as modelApi from "../api/models";
import * as taskApi from "../api/tasks";

const { Sider, Content } = Layout;

export default function TemplateEditor() {
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const editorRef = useRef<TinyMCEEditor | null>(null);
  const selectionRef = useRef<{ start: number; end: number; text: string } | null>(null);

  const [htmlContent, setHtmlContent] = useState("");
  const [templateName, setTemplateName] = useState("");
  const [points, setPoints] = useState<GenerationPoint[]>([]);
  const [models, setModels] = useState<AIModel[]>([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [pointModalOpen, setPointModalOpen] = useState(false);
  const [editingPoint, setEditingPoint] = useState<GenerationPoint | null>(null);
  const [showSelectionBtn, setShowSelectionBtn] = useState(false);
  const [selBtnPos, setSelBtnPos] = useState({ x: 0, y: 0 });
  const [pointForm] = Form.useForm();
  const [panelCollapsed, setPanelCollapsed] = useState(false);

  const [generating, setGenerating] = useState(false);
  const [taskStatus, setTaskStatus] = useState<GenerationTask | null>(null);
  const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const loadData = useCallback(async () => {
    if (!id) return;
    setLoading(true);
    try {
      const [template, pointsData, modelsData] = await Promise.all([
        templateApi.getTemplate(id),
        pointApi.listGenerationPoints(id),
        modelApi.listModels({ enabled: true }),
      ]);
      setTemplateName(template.name);
      setHtmlContent(template.html_content || "");
      setPoints(pointsData);
      setModels(modelsData);
    } catch {
      message.error("加载数据失败");
    } finally {
      setLoading(false);
    }
  }, [id]);

  useEffect(() => {
    loadData();
    return () => {
      if (pollingRef.current) clearInterval(pollingRef.current);
    };
  }, [loadData]);

  const handleSave = async () => {
    if (!id) return;
    setSaving(true);
    try {
      const html = editorRef.current?.getContent() || htmlContent;
      await templateApi.updateTemplateHtml(id, html);
      setHtmlContent(html);
      message.success("保存成功");
    } catch {
      message.error("保存失败");
    } finally {
      setSaving(false);
    }
  };

  const handleEditorInit = (_evt: unknown, editor: TinyMCEEditor) => {
    editorRef.current = editor;
    editor.on("selectionchange", () => {
      const sel = editor.selection.getContent({ format: "text" });
      if (sel && sel.trim().length > 0) {
        const content = editor.getContent();
        const rng = editor.selection.getRng();
        if (rng) {
          const preRange = rng.cloneRange();
          preRange.selectNodeContents(editor.getBody());
          preRange.setEnd(rng.startContainer, rng.startOffset);
          const start = preRange.toString().length;
          const end = start + sel.length;
          selectionRef.current = { start, end, text: sel.trim() };
        }
        const ed = editor.getContainer();
        const rect = ed.getBoundingClientRect();
        setSelBtnPos({ x: rect.left + 100, y: rect.top + 10 });
        setShowSelectionBtn(true);
      } else {
        setShowSelectionBtn(false);
      }
    });
  };

  const handleCreatePoint = () => {
    setEditingPoint(null);
    pointForm.resetFields();
    if (selectionRef.current) {
      pointForm.setFieldsValue({
        prompt: `根据上下文生成关于「${selectionRef.current.text.slice(0, 20)}...」的内容`,
      });
    }
    setPointModalOpen(true);
  };

  const handleEditPoint = (point: GenerationPoint) => {
    setEditingPoint(point);
    pointForm.setFieldsValue({
      prompt: point.prompt,
      model_id: point.model_id,
    });
    setPointModalOpen(true);
  };

  const handlePointSubmit = async () => {
    if (!id) return;
    try {
      const values = await pointForm.validateFields();
      const position = selectionRef.current
        ? { start: selectionRef.current.start, end: selectionRef.current.end }
        : editingPoint?.position;

      const refFile = values.ref_file?.fileList?.[0]?.originFileObj;

      if (editingPoint) {
        const updateData: Record<string, unknown> = {};
        if (values.prompt) updateData.prompt = values.prompt;
        if (values.model_id) updateData.model_id = values.model_id;
        await pointApi.updateGenerationPoint(editingPoint.id, updateData);
        message.success("更新成功");
      } else if (position) {
        await pointApi.createGenerationPoint({
          template_id: id,
          position: JSON.stringify(position),
          prompt: values.prompt,
          model_id: values.model_id,
          order: points.length,
          ref_file: refFile,
        });
        message.success("创建成功");
        selectionRef.current = null;
        setShowSelectionBtn(false);
      } else {
        message.warning("请先在编辑器中选中文本");
        return;
      }

      setPointModalOpen(false);
      const updated = await pointApi.listGenerationPoints(id);
      setPoints(updated);
    } catch (err: unknown) {
      if (err instanceof Error) message.error(err.message);
    }
  };

  const handleDeletePoint = async (pointId: string) => {
    await pointApi.deleteGenerationPoint(pointId);
    message.success("删除成功");
    const updated = await pointApi.listGenerationPoints(id!);
    setPoints(updated);
  };

  const handleTestPoint = async (pointId: string) => {
    try {
      message.loading({ content: "测试中...", key: "test" });
      const result = await pointApi.testGenerationPoint(pointId);
      message.success({ content: "测试完成", key: "test" });
      Modal.info({ title: "AI 生成结果", content: result, width: 600 });
    } catch {
      message.error({ content: "测试失败", key: "test" });
    }
  };

  const handleGenerate = async () => {
    if (!id) return;
    if (points.length === 0) {
      message.warning("请先添加至少一个生成点");
      return;
    }
    setGenerating(true);
    try {
      const { task_id } = await taskApi.triggerGeneration(id);
      pollingRef.current = setInterval(async () => {
        try {
          const status = await taskApi.getTaskStatus(task_id);
          setTaskStatus(status);
          if (status.status === "done" || status.status === "failed") {
            if (pollingRef.current) clearInterval(pollingRef.current);
            if (status.status === "done") {
              message.success("生成完成！");
            } else {
              message.error(`生成失败: ${status.error_msg}`);
            }
            setGenerating(false);
          }
        } catch {
          if (pollingRef.current) clearInterval(pollingRef.current);
          setGenerating(false);
        }
      }, 2000);
    } catch (err: unknown) {
      if (err instanceof Error) message.error(err.message);
      setGenerating(false);
    }
  };

  const handleDownload = (format: "docx" | "pdf" = "docx") => {
    if (taskStatus?.id) {
      window.open(taskApi.getTaskDownloadUrl(taskStatus.id, format));
    }
  };

  if (loading) {
    return (
      <div style={{ textAlign: "center", padding: 100 }}>
        <Spin size="large" />
      </div>
    );
  }

  return (
    <div style={{ height: "calc(100vh - 120px)" }}>
      <div
        style={{
          marginBottom: 12,
          display: "flex",
          justifyContent: "space-between",
          alignItems: "center",
        }}
      >
        <Space>
          <Button icon={<ArrowLeftOutlined />} onClick={() => navigate("/templates")}>
            返回
          </Button>
          <h3 style={{ margin: 0 }}>{templateName}</h3>
        </Space>
        <Space>
          <Button
            icon={panelCollapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
            onClick={() => setPanelCollapsed(!panelCollapsed)}
          />
          <Button icon={<SaveOutlined />} onClick={handleSave} loading={saving}>
            保存
          </Button>
          <Button
            type="primary"
            danger
            icon={<ThunderboltOutlined />}
            onClick={handleGenerate}
            loading={generating}
          >
            生成文档
          </Button>
          {taskStatus?.status === "done" && (
            <>
              <Button icon={<DownloadOutlined />} onClick={() => handleDownload("docx")}>
                DOCX
              </Button>
              <Button onClick={() => handleDownload("pdf")}>PDF</Button>
            </>
          )}
        </Space>
      </div>
      {taskStatus && taskStatus.status !== "done" && taskStatus.status !== "failed" && (
        <div style={{ marginBottom: 12 }}>
          <Progress
            percent={taskStatus.status === "processing" ? 50 : 10}
            status="active"
            format={() => taskStatus.status === "pending" ? "等待中..." : "生成中..."}
          />
        </div>
      )}
      {taskStatus?.status === "failed" && (
        <div style={{ marginBottom: 12, color: "red" }}>失败: {taskStatus.error_msg}</div>
      )}
      <Layout style={{ height: "calc(100% - 50px)", background: "#fff" }}>
        <Content style={{ position: "relative", overflow: "hidden" }}>
          {showSelectionBtn && (
            <Button
              type="primary"
              size="small"
              icon={<PlusOutlined />}
              onClick={handleCreatePoint}
              style={{
                position: "absolute",
                zIndex: 1310,
                top: 8,
                left: 8,
              }}
            >
              设为 AI 生成点
            </Button>
          )}
          <Editor
            tinymceScriptSrc="/tinymce/tinymce.min.js"
            onInit={handleEditorInit}
            value={htmlContent}
            init={{
              height: "100%",
              menubar: true,
              plugins: [
                "advlist", "autolink", "lists", "link", "image",
                "charmap", "preview", "anchor", "searchreplace",
                "visualblocks", "code", "fullscreen", "insertdatetime",
                "media", "table", "help", "wordcount",
              ],
              toolbar:
                "undo redo | blocks | bold italic forecolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help",
              content_style: "body { font-family: Arial, sans-serif; font-size: 14px; }",
              setup: (editor) => {
                editor.on("init", () => {
                  handleEditorInit(null, editor);
                });
              },
            }}
          />
        </Content>
        {!panelCollapsed && (
          <Sider width={320} theme="light" style={{ padding: 16, overflow: "auto", borderLeft: "1px solid #f0f0f0" }}>
            <h4 style={{ marginBottom: 12 }}>生成点列表 ({points.length})</h4>
            {points.map((point, index) => {
              const model = models.find((m) => m.id === point.model_id);
              return (
                <Card
                  key={point.id}
                  size="small"
                  style={{ marginBottom: 8 }}
                  title={
                    <Space size={4}>
                      <span style={{ fontSize: 12, color: "#999" }}>#{index + 1}</span>
                      {model && (
                        <span style={{ fontSize: 12, color: "#1677ff" }}>
                          {model.name}
                        </span>
                      )}
                    </Space>
                  }
                  extra={
                    <Space size={4}>
                      <Button
                        type="text"
                        size="small"
                        icon={<ExperimentOutlined />}
                        onClick={() => handleTestPoint(point.id)}
                      />
                      <Button
                        type="text"
                        size="small"
                        icon={<EditOutlined />}
                        onClick={() => handleEditPoint(point)}
                      />
                      <Popconfirm
                        title="确定删除？"
                        onConfirm={() => handleDeletePoint(point.id)}
                      >
                        <Button type="text" size="small" danger icon={<DeleteOutlined />} />
                      </Popconfirm>
                    </Space>
                  }
                >
                  <p style={{ fontSize: 12, color: "#666", margin: 0, wordBreak: "break-all" }}>
                    {point.prompt.slice(0, 80)}
                    {point.prompt.length > 80 && "..."}
                  </p>
                </Card>
              );
            })}
            {points.length === 0 && (
              <p style={{ color: "#999", fontSize: 13 }}>
                选中编辑器中的文本，点击"设为 AI 生成点"
              </p>
            )}
          </Sider>
        )}
      </Layout>

      <Modal
        title={editingPoint ? "编辑生成点" : "新建生成点"}
        open={pointModalOpen}
        onCancel={() => setPointModalOpen(false)}
        onOk={handlePointSubmit}
        width={560}
        destroyOnClose
      >
        <Form form={pointForm} layout="vertical" preserve={false}>
          {selectionRef.current && !editingPoint && (
            <div
              style={{
                marginBottom: 12,
                padding: 8,
                background: "#f6f8fa",
                borderRadius: 6,
                fontSize: 13,
                color: "#666",
              }}
            >
              已选中: 「{selectionRef.current.text.slice(0, 50)}
              {selectionRef.current.text.length > 50 ? "..." : ""}」
            </div>
          )}
          <Form.Item name="prompt" label="提示词" rules={[{ required: true }]}>
            <Input.TextArea
              rows={4}
              placeholder="请输入 AI 生成提示词，例如：请根据参考文件内容，生成一段项目背景介绍..."
            />
          </Form.Item>
          <Form.Item name="model_id" label="AI 模型">
            <Select
              allowClear
              placeholder="留空则使用全局默认模型"
              options={models.map((m) => ({ label: m.name, value: m.id }))}
            />
          </Form.Item>
          {!editingPoint && (
            <Form.Item name="ref_file" label="参考文件" valuePropName="fileList" getValueFromEvent={(e) => e.fileList}>
              <Upload maxCount={1} beforeUpload={() => false}>
                <Button icon={<PlusOutlined />}>上传参考文件</Button>
              </Upload>
            </Form.Item>
          )}
        </Form>
      </Modal>
    </div>
  );
}
