import {
  ArrowLeftOutlined,
  CheckCircleOutlined,
  FileTextOutlined,
  LoginOutlined,
  PictureOutlined,
  UploadOutlined,
} from "@ant-design/icons";
import { useEffect, useMemo, useRef, useState, type ChangeEvent, type DragEvent } from "react";
import { aiGenerationClient } from "../../api/aiGenerationClient";
import { communityClient } from "../../api/communityClient";
import WorkspacePageShell from "../../components/WorkspacePageShell";
import "../../styles/pages/compliance.css";
import type { WebCanvasWorkflow, WebUserSession } from "../../types";
import { getWorkflowCoverUrl, isCanvasWorkflow } from "../community/communityCaseUtils";
import { canManageCommunityCases } from "./communityPermissions";

interface CommunityCaseAddPageProps {
  session: WebUserSession | null;
  onOpenLogin: () => void;
  onOpenReview: () => void;
}

type CaseTarget = "generation" | "canvas";

const RATIO_OPTIONS = ["16:9", "9:16", "1:1", "4:5", "3:4", "21:9"];

function readFileAsDataUrl(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result || ""));
    reader.onerror = () => reject(reader.error || new Error("图片读取失败"));
    reader.readAsDataURL(file);
  });
}

function readFileAsText(file: File): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result || ""));
    reader.onerror = () => reject(reader.error || new Error("JSON 读取失败"));
    reader.readAsText(file);
  });
}

function textToDataUrl(text: string, mimeType: string): string {
  const bytes = new TextEncoder().encode(text);
  let binary = "";
  bytes.forEach((byte) => {
    binary += String.fromCharCode(byte);
  });
  return `data:${mimeType};base64,${btoa(binary)}`;
}

function parseWorkflowText(text: string): WebCanvasWorkflow {
  const parsed = JSON.parse(text) as unknown;
  if (!isCanvasWorkflow(parsed)) {
    throw new Error("JSON 需要包含完整画布工作流：nodes、edges 和 settings。");
  }
  return parsed;
}

function shortDescription(value: string): string {
  return value.trim().replace(/\s+/g, " ").slice(0, 120);
}

function ratioToCssAspectRatio(value: string): string {
  const [width, height] = value.split(":").map((item) => Number(item));
  return width > 0 && height > 0 ? `${width} / ${height}` : "16 / 9";
}

export default function CommunityCaseAddPage({ session, onOpenLogin, onOpenReview }: CommunityCaseAddPageProps) {
  const allowed = canManageCommunityCases(session);
  const imageInputRef = useRef<HTMLInputElement | null>(null);
  const workflowInputRef = useRef<HTMLInputElement | null>(null);
  const [isImageDragging, setIsImageDragging] = useState(false);
  const [isWorkflowDragging, setIsWorkflowDragging] = useState(false);

  const handleImageDragOver = (e: DragEvent) => { e.preventDefault(); if (e.dataTransfer.types.includes("Files")) setIsImageDragging(true); };
  const handleImageDragLeave = (e: DragEvent) => { e.preventDefault(); if (!e.currentTarget.contains(e.relatedTarget as Node)) setIsImageDragging(false); };
  const handleImageDrop = (e: DragEvent) => {
    e.preventDefault();
    setIsImageDragging(false);
    if (e.dataTransfer.files.length) {
      void handleImageChange({ target: { files: e.dataTransfer.files } } as ChangeEvent<HTMLInputElement>);
    }
  };

  const handleWorkflowDragOver = (e: DragEvent) => { e.preventDefault(); if (e.dataTransfer.types.includes("Files")) setIsWorkflowDragging(true); };
  const handleWorkflowDragLeave = (e: DragEvent) => { e.preventDefault(); if (!e.currentTarget.contains(e.relatedTarget as Node)) setIsWorkflowDragging(false); };
  const handleWorkflowDrop = (e: DragEvent) => {
    e.preventDefault();
    setIsWorkflowDragging(false);
    if (e.dataTransfer.files.length) {
      void handleWorkflowChange({ target: { files: e.dataTransfer.files } } as ChangeEvent<HTMLInputElement>);
    }
  };

  const [target, setTarget] = useState<CaseTarget>("generation");
  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [category, setCategory] = useState("图片案例");
  const [ratio, setRatio] = useState("16:9");
  const [prompt, setPrompt] = useState("");
  const [imageUrl, setImageUrl] = useState("");
  const [imageDataUrl, setImageDataUrl] = useState("");
  const [imageFileName, setImageFileName] = useState("");
  const [workflowText, setWorkflowText] = useState("");
  const [workflowFileName, setWorkflowFileName] = useState("");
  const [workflow, setWorkflow] = useState<WebCanvasWorkflow | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [notice, setNotice] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const previewUrl = imageDataUrl || imageUrl.trim();
  const workflowCoverUrl = useMemo(() => getWorkflowCoverUrl(workflow), [workflow]);
  const targetCopy = target === "generation" ? "生成页面社区" : "画布页面社区";
  const previewAspectRatio = target === "generation" ? ratioToCssAspectRatio(ratio) : "16 / 10";

  useEffect(() => {
    setCategory((current) => {
      if (target === "generation" && current === "工作流案例") return "图片案例";
      if (target === "canvas" && current === "图片案例") return "工作流案例";
      return current;
    });
  }, [target]);

  const handleImageChange = async (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;
    setError(null);
    setImageFileName(file.name);
    setImageDataUrl(await readFileAsDataUrl(file));
  };

  const applyWorkflowText = (text: string, fileName = "") => {
    setWorkflowText(text);
    setWorkflowFileName(fileName);
    try {
      const parsedWorkflow = parseWorkflowText(text);
      setWorkflow(parsedWorkflow);
      setError(null);
      if (!title.trim()) setTitle(parsedWorkflow.title || "画布社区案例");
      if (!description.trim()) setDescription(parsedWorkflow.description || "");
      if (!category.trim()) setCategory("工作流案例");
    } catch (parseError) {
      setWorkflow(null);
      setError(parseError instanceof Error ? parseError.message : "JSON 解析失败");
    }
  };

  const handleWorkflowChange = async (event: ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;
    applyWorkflowText(await readFileAsText(file), file.name);
  };

  const handleSubmit = async () => {
    if (submitting) return;
    setSubmitting(true);
    setNotice(null);
    setError(null);
    try {
      const cleanTitle = title.trim();
      if (!cleanTitle) throw new Error("请填写案例标题。");

      if (target === "generation") {
        if (!prompt.trim()) throw new Error("请填写生成页面展示的提示词。");
        if (!previewUrl) throw new Error("请上传案例图片或填写图片 URL。");

        let coverUrl = imageUrl.trim();
        let ossKey: string | undefined;
        if (imageDataUrl) {
          const uploaded = await aiGenerationClient.uploadAsset({
            dataUrl: imageDataUrl,
            name: imageFileName || `${cleanTitle}.png`,
            scope: "community-case-cover",
          });
          coverUrl = uploaded.url || imageDataUrl;
          ossKey = uploaded.ossKey;
        }

        await communityClient.publishCase({
          title: cleanTitle,
          description: description.trim() || shortDescription(prompt),
          coverUrl,
          tags: [category.trim() || "图片案例", "生成页面社区"],
          metadata: {
            source: "admin-case-add",
            communitySurface: "generation",
            prompt: prompt.trim(),
            ratio,
            category: category.trim() || "图片案例",
          },
          assets: [
            {
              assetType: "cover",
              title: cleanTitle,
              url: coverUrl,
              ossKey,
              metadata: { prompt: prompt.trim(), ratio },
            },
          ],
        });
      } else {
        if (!workflow) throw new Error("请上传或粘贴有效的画布工作流 JSON。");
        const workflowJson = JSON.stringify(workflow);
        const uploadedWorkflow = await aiGenerationClient.uploadAsset({
          dataUrl: textToDataUrl(workflowJson, "application/json"),
          name: workflowFileName || `${cleanTitle}.json`,
          mimeType: "application/json",
          scope: "community-case-workflow",
        });
        const coverUrl = workflowCoverUrl || imageUrl.trim();
        await communityClient.publishCase({
          title: cleanTitle,
          description: description.trim() || workflow.description || "管理员添加的画布工作流案例。",
          coverUrl,
          tags: [category.trim() || "工作流案例", "画布页面社区"],
          metadata: {
            source: "admin-case-add",
            communitySurface: "canvas",
            category: category.trim() || "工作流案例",
            workflow,
            workflowOssKey: uploadedWorkflow.ossKey || null,
            workflowUrl: uploadedWorkflow.url || null,
          },
          assets: [
            {
              assetType: "workflow",
              title: cleanTitle,
              url: uploadedWorkflow.url,
              ossKey: uploadedWorkflow.ossKey,
              metadata: { workflow, fileName: workflowFileName || null, contentType: "application/json" },
            },
          ],
        });
      }

      setNotice(`已提交到${targetCopy}审核列表，审核通过后会展示到对应社区。`);
    } catch (submitError) {
      setError(submitError instanceof Error ? submitError.message : "案例提交失败");
    } finally {
      setSubmitting(false);
    }
  };

  if (!session) {
    return (
      <WorkspacePageShell title="添加案例" fullWidth className="community-review-page page-motion">
        <section className="community-review-access">
          <LoginOutlined />
          <h1>请登录工作人员账号</h1>
          <p>添加社区案例需要登录后访问。</p>
          <button type="button" onClick={onOpenLogin}>登录 / 注册</button>
        </section>
      </WorkspacePageShell>
    );
  }

  if (!allowed) {
    return (
      <WorkspacePageShell title="添加案例" fullWidth className="community-review-page page-motion">
        <section className="community-review-access">
          <FileTextOutlined />
          <h1>当前账号没有管理权限</h1>
          <p>请切换到 admin 角色账号后再添加案例。</p>
        </section>
      </WorkspacePageShell>
    );
  }

  return (
    <WorkspacePageShell title="添加案例" fullWidth className="community-review-page page-motion">
      <div className="community-review-page__inner">
        <section className="community-review-toolbar">
          <div>
            <span>内部案例录入</span>
            <h1>添加社区案例</h1>
            <p>管理员录入的案例会先进入社区审核，审核通过后才展示给用户。</p>
          </div>
          <div className="community-review-toolbar__actions">
            <button type="button" onClick={onOpenReview}>
              <ArrowLeftOutlined />
              返回审核
            </button>
          </div>
        </section>

        <div className="community-review-tabs community-case-add-targets" role="tablist" aria-label="案例展示位置">
          <button
            type="button"
            role="tab"
            aria-selected={target === "generation"}
            className={target === "generation" ? "is-active" : ""}
            onClick={() => setTarget("generation")}
          >
            <PictureOutlined />
            生成页面社区
          </button>
          <button
            type="button"
            role="tab"
            aria-selected={target === "canvas"}
            className={target === "canvas" ? "is-active" : ""}
            onClick={() => setTarget("canvas")}
          >
            <FileTextOutlined />
            画布页面社区
          </button>
        </div>

        {error ? <p className="community-review-error">{error}</p> : null}
        {notice ? (
          <p className="community-case-add-success">
            <CheckCircleOutlined />
            {notice}
          </p>
        ) : null}

        <section className="community-case-add-layout">
          <form className="community-case-add-form" onSubmit={(event) => event.preventDefault()}>
            <div className="community-case-add-form__grid">
              <label>
                <span>案例标题</span>
                <input value={title} onChange={(event) => setTitle(event.target.value)} placeholder="例如：横版商品主图" />
              </label>
              <label>
                <span>分类标签</span>
                <input value={category} onChange={(event) => setCategory(event.target.value)} placeholder="图片案例 / 工作流案例" />
              </label>
              {target === "generation" ? (
                <label>
                  <span>展示比例</span>
                  <select value={ratio} onChange={(event) => setRatio(event.target.value)}>
                    {RATIO_OPTIONS.map((option) => (
                      <option key={option} value={option}>{option}</option>
                    ))}
                  </select>
                </label>
              ) : null}
            </div>

            <label>
              <span>案例简介</span>
              <textarea value={description} onChange={(event) => setDescription(event.target.value)} placeholder="审核页和社区卡片使用的简短说明" />
            </label>

            {target === "generation" ? (
              <>
                <label>
                  <span>提示词</span>
                  <textarea value={prompt} onChange={(event) => setPrompt(event.target.value)} placeholder="输入用户点击案例后可套用的提示词" />
                </label>
                <div className="community-case-add-upload-row">
                  <input ref={imageInputRef} type="file" accept="image/*" hidden onChange={handleImageChange} />
                  <button
                    type="button"
                    className={isImageDragging ? "is-dragging" : ""}
                    onClick={() => imageInputRef.current?.click()}
                    onDragOver={handleImageDragOver}
                    onDragLeave={handleImageDragLeave}
                    onDrop={handleImageDrop}
                  >
                    <UploadOutlined />
                    上传图片
                  </button>
                  <label>
                    <span>或填写图片 URL</span>
                    <input value={imageUrl} onChange={(event) => setImageUrl(event.target.value)} placeholder="https://..." />
                  </label>
                </div>
              </>
            ) : (
              <>
                <div className="community-case-add-upload-row">
                  <input ref={workflowInputRef} type="file" accept="application/json,.json" hidden onChange={handleWorkflowChange} />
                  <button
                    type="button"
                    className={isWorkflowDragging ? "is-dragging" : ""}
                    onClick={() => workflowInputRef.current?.click()}
                    onDragOver={handleWorkflowDragOver}
                    onDragLeave={handleWorkflowDragLeave}
                    onDrop={handleWorkflowDrop}
                  >
                    <UploadOutlined />
                    上传 JSON
                  </button>
                  <label>
                    <span>可选封面 URL</span>
                    <input value={imageUrl} onChange={(event) => setImageUrl(event.target.value)} placeholder="未填写时从节点预览图提取" />
                  </label>
                </div>
                <label>
                  <span>画布工作流 JSON</span>
                  <textarea
                    value={workflowText}
                    onChange={(event) => applyWorkflowText(event.target.value, workflowFileName)}
                    placeholder='{"id":"...","version":1,"title":"...","nodes":[...],"edges":[...],"settings":{...}}'
                  />
                </label>
              </>
            )}

            <div className="community-case-add-actions">
              <button type="button" onClick={() => void handleSubmit()} disabled={submitting}>
                <CheckCircleOutlined />
                {submitting ? "提交中..." : "提交审核"}
              </button>
              <button type="button" onClick={onOpenReview}>
                查看审核列表
              </button>
            </div>
          </form>

          <aside className="community-case-add-preview">
            <span>{targetCopy}</span>
            <strong>{title.trim() || "未命名案例"}</strong>
            <p>{description.trim() || (target === "generation" ? shortDescription(prompt) : workflow?.description) || "提交前可在这里预览案例信息。"}</p>
            {target === "generation" ? (
              previewUrl ? (
                <img src={previewUrl} alt="" style={{ aspectRatio: previewAspectRatio }} />
              ) : (
                <div className="community-case-add-preview__empty" style={{ aspectRatio: previewAspectRatio }}>等待图片</div>
              )
            ) : workflowCoverUrl || imageUrl.trim() ? (
              <img src={workflowCoverUrl || imageUrl.trim()} alt="" />
            ) : (
              <div className="community-case-add-preview__empty">等待工作流封面</div>
            )}
            <dl>
              <dt>目标</dt>
              <dd>{targetCopy}</dd>
              <dt>{target === "generation" ? "比例" : "节点"}</dt>
              <dd>{target === "generation" ? ratio : workflow ? workflow.nodes.length : 0}</dd>
              <dt>文件</dt>
              <dd>{target === "generation" ? imageFileName || "未上传" : workflowFileName || "未上传"}</dd>
            </dl>
          </aside>
        </section>
      </div>
    </WorkspacePageShell>
  );
}
