import {
  ClockCircleOutlined,
  CloseOutlined,
  DatabaseOutlined,
  DeleteOutlined,
  FileImageOutlined,
  LoadingOutlined,
  LoginOutlined,
  PlusOutlined,
  SearchOutlined,
  UserOutlined,
} from "@ant-design/icons";
import { useCallback, useEffect, useMemo, useRef, useState, type DragEvent, type ReactElement } from "react";
import "../../styles/pages/assets.css";
import { assetClient, type ServerAssetItem } from "../../api/assetClient";
import { aiGenerationClient } from "../../api/aiGenerationClient";
import { useDebounce } from "../../hooks/useDebounce";
import OptimizedImage from "../../components/OptimizedImage";
import { SkeletonList } from "../../components/Skeleton";
import { EmptyState } from "../../components/EmptyState";
import WorkspacePageShell from "../../components/WorkspacePageShell";
import type { WebAssetItem } from "../../types";

type AssetTypeFilter = WebAssetItem["type"] | "all";

type LibraryAssetItem = WebAssetItem & {
  project: string;
  version: string;
  ratio: string;
  tags: string[];
  thumbClass: string;
};

interface AssetsPageProps {
  isAuthenticated: boolean;
  onOpenLogin: () => void;
}

const typeTabs: Array<{ key: AssetTypeFilter; label: string; icon: ReactElement | null }> = [
  { key: "all", label: "全部", icon: null },
  { key: "character", label: "人物", icon: <UserOutlined /> },
  { key: "scene", label: "场景", icon: <FileImageOutlined /> },
  { key: "prop", label: "物品", icon: <DatabaseOutlined /> },
  { key: "video", label: "视频", icon: <FileImageOutlined /> },
  { key: "image", label: "图片", icon: <FileImageOutlined /> },
  { key: "asset", label: "素材", icon: <DatabaseOutlined /> },
  { key: "other", label: "其他", icon: <DatabaseOutlined /> },
];

const statusLabel: Record<WebAssetItem["status"], string> = {
  ready: "已完成",
  draft: "草稿",
  reviewing: "复核中",
  pending: "同步中",
  failed: "失败",
};

const statusBadgeClass: Record<WebAssetItem["status"], string> = {
  ready: "studio-status-bar__badge--success",
  draft: "studio-status-bar__badge--idle",
  reviewing: "studio-status-bar__badge--running",
  pending: "studio-status-bar__badge--running",
  failed: "studio-status-bar__badge--danger",
};

function mapServerAsset(asset: ServerAssetItem): LibraryAssetItem {
  return {
    ...asset,
    project: asset.sourceProjectId || "服务器资产库",
    version: "Server",
    ratio: String(asset.metadata?.ratio || "1:1"),
    tags: asset.tags?.length ? asset.tags : ["服务器素材"],
    thumbClass: asset.imageUrl ? "is-uploaded" : "is-station",
  };
}

function getAssetPreviewUrl(asset: LibraryAssetItem) {
  return asset.url || asset.imageUrl;
}

function isVideoPreview(asset: LibraryAssetItem) {
  const url = getAssetPreviewUrl(asset) || "";
  return asset.type === "video" || /\.(mp4|webm|mov|m4v)(\?|#|$)/i.test(url);
}

function AssetsPage({ isAuthenticated, onOpenLogin }: AssetsPageProps) {
  const [activeType, setActiveType] = useState<AssetTypeFilter>("all");
  const [query, setQuery] = useState("");
  const debouncedQuery = useDebounce(query, 300);
  const [serverAssets, setServerAssets] = useState<ServerAssetItem[]>([]);
  const [serverNotice, setServerNotice] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [previewAsset, setPreviewAsset] = useState<LibraryAssetItem | null>(null);
  const [contextMenu, setContextMenu] = useState<{ x: number; y: number; asset: LibraryAssetItem } | null>(null);
  const contextMenuRef = useRef<HTMLDivElement>(null);
  const uploadInputRef = useRef<HTMLInputElement>(null);
  const [isUploadDragging, setIsUploadDragging] = useState(false);

  const handleUploadDragOver = (e: DragEvent) => { e.preventDefault(); if (e.dataTransfer.types.includes("Files")) setIsUploadDragging(true); };
  const handleUploadDragLeave = (e: DragEvent) => { e.preventDefault(); if (!e.currentTarget.contains(e.relatedTarget as Node)) setIsUploadDragging(false); };
  const handleUploadDrop = (e: DragEvent) => {
    e.preventDefault();
    setIsUploadDragging(false);
    if (e.dataTransfer.files.length) {
      void handleUploadFiles(e.dataTransfer.files);
    }
  };

  const handleContextMenu = useCallback((e: React.MouseEvent, asset: LibraryAssetItem) => {
    e.preventDefault();
    setContextMenu({ x: e.clientX, y: e.clientY, asset });
  }, []);

  const handleDeleteAsset = useCallback(async (asset?: LibraryAssetItem) => {
    const target = asset || contextMenu?.asset;
    if (!target) return;
    setContextMenu(null);
    try {
      await assetClient.delete(target.id);
      setServerAssets((prev) => prev.filter((a) => a.id !== target.id));
      setServerNotice(`已删除 ${target.name}`);
    } catch (err) {
      setServerNotice(err instanceof Error ? err.message : "删除失败");
    }
  }, [contextMenu]);

  const handleUploadFiles = useCallback(async (files: FileList | null) => {
    if (!files || files.length === 0) return;
    setIsUploading(true);
    setServerNotice("正在上传...");
    let successCount = 0;
    for (const file of Array.from(files)) {
      try {
        const dataUrl = await new Promise<string>((resolve, reject) => {
          const reader = new FileReader();
          reader.onload = () => resolve(reader.result as string);
          reader.onerror = () => reject(new Error("读取文件失败"));
          reader.readAsDataURL(file);
        });
        const mimeType = file.type || (file.name.match(/\.(mp4|mov|webm)$/i) ? "video/mp4" : "image/png");
        const uploaded = await aiGenerationClient.uploadAsset({ dataUrl, name: file.name, mimeType, scope: "asset-library" });
        const isVideo = mimeType.startsWith("video/");
        const created = await assetClient.create({
          type: isVideo ? "video" : "image",
          name: file.name.replace(/\.[^.]+$/, ""),
          description: `手动上传 · ${file.name}`,
          url: uploaded.url,
          imageUrl: isVideo ? "" : uploaded.url,
          status: "ready",
          tags: ["手动上传"],
        });
        setServerAssets((prev) => [created, ...prev]);
        successCount++;
      } catch (err) {
        setServerNotice(err instanceof Error ? err.message : `上传 ${file.name} 失败`);
      }
    }
    setIsUploading(false);
    if (successCount > 0) setServerNotice(`已上传 ${successCount} 个文件`);
    if (uploadInputRef.current) uploadInputRef.current.value = "";
  }, []);

  useEffect(() => {
    if (!contextMenu) return undefined;
    const handleClick = (e: MouseEvent) => {
      if (contextMenuRef.current && !contextMenuRef.current.contains(e.target as Node)) {
        setContextMenu(null);
      }
    };
    window.addEventListener("mousedown", handleClick);
    return () => window.removeEventListener("mousedown", handleClick);
  }, [contextMenu]);

  useEffect(() => {
    if (!isAuthenticated) {
      setServerAssets([]);
      setServerNotice(null);
      setIsLoading(false);
      return;
    }

    let cancelled = false;
    setIsLoading(true);
    setServerNotice("正在同步服务器资产");

    assetClient
      .list()
      .then((items) => {
        if (cancelled) return;
        setServerAssets(items);
        setServerNotice(items.length ? "服务器资产已同步" : "暂无资产");
      })
      .catch((error) => {
        if (cancelled) return;
        setServerAssets([]);
        setServerNotice(error instanceof Error && error.message ? error.message : "资产服务器暂时不可用");
      })
      .finally(() => {
        if (!cancelled) setIsLoading(false);
      });

    return () => {
      cancelled = true;
    };
  }, [isAuthenticated]);

  const allAssets = useMemo<LibraryAssetItem[]>(() => {
    return serverAssets.map(mapServerAsset);
  }, [serverAssets]);

  const visibleAssets = useMemo(() => {
    const normalizedQuery = debouncedQuery.trim().toLowerCase();
    return allAssets.filter((asset) => {
      const typeMatched = activeType === "all" || asset.type === activeType;
      const queryMatched =
        !normalizedQuery ||
        asset.name.toLowerCase().includes(normalizedQuery) ||
        asset.description.toLowerCase().includes(normalizedQuery) ||
        asset.tags.some((tag) => tag.toLowerCase().includes(normalizedQuery));
      return typeMatched && queryMatched;
    });
  }, [activeType, allAssets, debouncedQuery]);

  const completeCount = allAssets.filter((asset) => asset.status === "ready").length;
  const latestAsset = allAssets[0];

  useEffect(() => {
    if (!previewAsset) return undefined;
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "Escape") {
        setPreviewAsset(null);
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [previewAsset]);

  if (!isAuthenticated) {
    return (
      <WorkspacePageShell title="资产库" fullWidth className="assets-page page-motion">
        <div className="assets-centered-page assets-centered-page--empty">
          <div className="assets-login-required" role="status">
            <div className="assets-login-required__icon">
              <LoginOutlined />
            </div>
            <strong>请登录</strong>
            <p>登录后可查看与管理你的云端资产库。</p>
            <button type="button" className="studio-generate-btn" onClick={onOpenLogin}>
              <LoginOutlined />
              登录 / 注册
            </button>
          </div>
        </div>
      </WorkspacePageShell>
    );
  }

  return (
    <WorkspacePageShell title="资产库" fullWidth className="assets-page page-motion">
      <div className="assets-centered-page">
        <div className="assets-centered-page__head">
          <div className="studio-tabs">
            {typeTabs.map((tab) => (
              <button
                key={tab.key}
                type="button"
                className={activeType === tab.key ? "is-active" : ""}
                onClick={() => setActiveType(tab.key)}
              >
                {tab.icon}
                {tab.label}
              </button>
            ))}
          </div>
          <label className="asset-search">
            <SearchOutlined />
            <input
              value={query}
              onChange={(e) => setQuery(e.target.value)}
              placeholder="搜索资产..."
            />
          </label>
          <button
            type="button"
            className={`studio-generate-btn studio-generate-btn--compact${isUploadDragging ? " is-dragging" : ""}`}
            onClick={() => uploadInputRef.current?.click()}
            onDragOver={handleUploadDragOver}
            onDragLeave={handleUploadDragLeave}
            onDrop={handleUploadDrop}
            disabled={isUploading}
          >
            {isUploading ? <LoadingOutlined /> : <PlusOutlined />}
            {isUploading ? "上传中..." : "添加"}
          </button>
          <input
            ref={uploadInputRef}
            type="file"
            accept="image/*,video/*"
            multiple
            style={{ display: "none" }}
            onChange={(e) => void handleUploadFiles(e.target.files)}
          />
        </div>

        <div className="assets-centered-page__body">
          {visibleAssets.length ? (
            <div className="asset-grid asset-grid--desktop motion-stagger">
              {visibleAssets.map((asset) => (
                <div key={asset.id} className="asset-card-wrapper">
                  <button
                    type="button"
                    className="asset-card asset-card--desktop"
                    onClick={() => setPreviewAsset(asset)}
                    onContextMenu={(e) => handleContextMenu(e, asset)}
                    aria-label={`预览素材 ${asset.name}`}
                  >
                    <div className={`asset-card__thumb ${asset.thumbClass}`}>
                      {asset.imageUrl ? <OptimizedImage src={asset.imageUrl} alt={asset.name} /> : null}
                    </div>
                    <div className="asset-card__body">
                      <div className="asset-card__head">
                        <strong>{asset.name}</strong>
                        <span className={`studio-status-bar__badge ${statusBadgeClass[asset.status]}`}>
                          {statusLabel[asset.status]}
                        </span>
                      </div>
                      <p className="asset-card__desc">{asset.description}</p>
                      <div className="asset-card__tags">
                        {asset.tags.slice(0, 2).map((tag) => (
                          <span key={tag}>{tag}</span>
                        ))}
                      </div>
                    </div>
                  </button>
                  <button
                    type="button"
                    className="asset-card__delete"
                    title="删除素材"
                    onClick={(e) => { e.stopPropagation(); void handleDeleteAsset(asset); }}
                    aria-label={`删除 ${asset.name}`}
                  >
                    <DeleteOutlined />
                  </button>
                </div>
              ))}
            </div>
          ) : isLoading ? (
            <SkeletonList count={6} />
          ) : (
            <EmptyState
              icon={<FileImageOutlined style={{ fontSize: 48 }} />}
              title="暂无资产"
              description="在工作台生成图片或视频后，素材会自动同步到这里。"
            />
          )}
        </div>

        <footer className="assets-centered-page__footer">
          <span className="studio-status-bar__badge studio-status-bar__badge--success">
            {isLoading ? "同步中" : "就绪"}
          </span>
          <span className="studio-status-bar__text">
            已加载 {allAssets.length} 个资产，{completeCount} 个已完成
          </span>
          {serverNotice ? <span className="studio-status-bar__meta">{serverNotice}</span> : null}
          {latestAsset ? (
            <span className="studio-status-bar__meta">
              <ClockCircleOutlined /> 最近更新 {latestAsset.updatedAt}
            </span>
          ) : null}
        </footer>

        {previewAsset ? (
          <div className="asset-preview-modal" role="dialog" aria-modal="true" aria-label={`预览素材 ${previewAsset.name}`}>
            <button
              type="button"
              className="asset-preview-modal__backdrop"
              aria-label="关闭预览"
              onClick={() => setPreviewAsset(null)}
            />
            <section className="asset-preview-modal__panel" onClick={(event) => event.stopPropagation()}>
              <header className="asset-preview-modal__head">
                <div>
                  <strong>{previewAsset.name}</strong>
                  <span>{previewAsset.description}</span>
                </div>
                <button type="button" className="asset-preview-modal__close" aria-label="关闭预览" onClick={() => setPreviewAsset(null)}>
                  <CloseOutlined />
                </button>
              </header>
              <div className="asset-preview-modal__body">
                {getAssetPreviewUrl(previewAsset) ? (
                  isVideoPreview(previewAsset) ? (
                    <video src={getAssetPreviewUrl(previewAsset) || undefined} controls playsInline />
                  ) : (
                    <img src={getAssetPreviewUrl(previewAsset) || undefined} alt={previewAsset.name} />
                  )
                ) : (
                  <div className="asset-preview-modal__empty">
                    <FileImageOutlined />
                    <strong>暂无可预览素材</strong>
                  </div>
                )}
              </div>
              <footer className="asset-preview-modal__meta">
                <span>{statusLabel[previewAsset.status]}</span>
                <span>{previewAsset.ratio}</span>
                <span>{previewAsset.project}</span>
                <span>{previewAsset.updatedAt}</span>
              </footer>
            </section>
          </div>
        ) : null}

        {contextMenu ? (
          <div
            ref={contextMenuRef}
            className="asset-context-menu"
            style={{ top: contextMenu.y, left: contextMenu.x }}
          >
            <button type="button" onClick={() => void handleDeleteAsset()}>
              <DeleteOutlined />
              删除资产
            </button>
          </div>
        ) : null}
      </div>
    </WorkspacePageShell>
  );
}

export default AssetsPage;
