"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useDropzone } from "react-dropzone";
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";
import type { MediaAsset, MediaKind, MediaSelection } from "@/types/media";
import { emitAssetsChanged } from "@/lib/events";

export type PickerTab = "upload" | "recent" | "link" | "icon";

interface ImagePickerDialogProps {
  open: boolean;
  defaultTab: PickerTab;
  mediaType: MediaKind;
  multiple?: boolean;
  documentId: string;
  workspaceId: string;
  onClose: () => void;
  onSelect: (selection: MediaSelection) => void;
}

const ICON_PRESETS: Array<{ id: string; label: string; url: string }> = [
  { id: "progress", label: "进度波纹", url: "https://media.giphy.com/media/QBd2kLB5qDmysEXre9/giphy.gif" },
  { id: "heartbeat", label: "心跳", url: "https://media.giphy.com/media/HEPwfdu6T6svpPE1eN/giphy.gif" },
  { id: "sparkles", label: "闪光", url: "https://media.giphy.com/media/f9jQLaPmuFKfa7E55Q/giphy.gif" },
  { id: "loading", label: "加载", url: "https://media.giphy.com/media/52qtwCtj9OLTi/giphy.gif" },
];

const MEDIA_TABS: Record<MediaKind, PickerTab[]> = {
  image: ["upload", "recent", "link", "icon"],
  video: ["upload", "recent", "link"],
  audio: ["upload", "recent", "link"],
  file: ["upload", "recent", "link"],
};

const TAB_LABELS: Record<PickerTab, string> = {
  upload: "上传",
  recent: "最近",
  link: "链接",
  icon: "动态图标",
};

const MEDIA_ACCEPTS: Record<MediaKind, Record<string, string[]> | null> = {
  image: { "image/*": [] },
  video: { "video/*": [] },
  audio: { "audio/*": [] },
  file: null,
};

const MEDIA_TITLES: Record<MediaKind, string> = {
  image: "选择图片",
  video: "选择视频",
  audio: "选择音频",
  file: "选择文件",
};

const formatBytes = (size?: number | null) => {
  if (!size || size <= 0) {
    return "";
  }
  const units = ["B", "KB", "MB", "GB", "TB"];
  let value = size;
  let index = 0;
  while (value >= 1024 && index < units.length - 1) {
    value /= 1024;
    index += 1;
  }
  return `${value.toFixed(value >= 10 ? 0 : 1)} ${units[index]}`;
};

const guessFileNameFromUrl = (url: string) => {
  try {
    const parsed = new URL(url);
    const name = parsed.pathname.split("/").filter(Boolean).pop();
    if (name) {
      return decodeURIComponent(name);
    }
  } catch {
    const segments = url.split("?")[0]?.split("/") ?? [];
    const name = segments.pop();
    if (name) {
      return decodeURIComponent(name);
    }
  }
  return "未命名资源";
};

export function ImagePickerDialog({
  open,
  defaultTab,
  mediaType,
  multiple = false,
  documentId,
  workspaceId,
  onClose,
  onSelect,
}: ImagePickerDialogProps) {
  const [tab, setTab] = useState<PickerTab>(defaultTab);
  const availableTabs = MEDIA_TABS[mediaType];
  const [recent, setRecent] = useState<MediaAsset[]>([]);
  const [recentLoading, setRecentLoading] = useState(false);
  const [linkUrl, setLinkUrl] = useState("");
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (open) {
      const availableTabs = MEDIA_TABS[mediaType];
      const fallback = availableTabs.includes(defaultTab) ? defaultTab : availableTabs[0];
      setTab(fallback);
    }
  }, [defaultTab, mediaType, open]);

  const fetchRecent = useCallback(async () => {
    if (!workspaceId) {
      return;
    }
    setRecentLoading(true);
    try {
      const response = await fetch(
        `/api/media/assets?workspaceId=${workspaceId}&assetType=${mediaType}`,
      );
      if (!response.ok) {
        throw new Error("无法获取最近上传");
      }
      const payload = (await response.json()) as { items: MediaAsset[] };
      setRecent(payload.items ?? []);
    } catch (err) {
      console.error(err);
      setRecent([]);
    } finally {
      setRecentLoading(false);
    }
  }, [workspaceId, mediaType]);

  useEffect(() => {
    if (open && tab === "recent") {
      void fetchRecent();
    }
  }, [open, tab, fetchRecent]);

  const uploadOne = useCallback(
    async (file: File) => {
      if (!workspaceId || !documentId) {
        throw new Error("缺少必要参数");
      }
      const form = new FormData();
      form.append("file", file);
      form.append("workspaceId", workspaceId);
      form.append("documentId", documentId);
      const response = await fetch("/api/media/upload", {
        method: "POST",
        body: form,
      });
      if (!response.ok) {
        const payload = await response.json().catch(() => null);
        throw new Error(payload?.error ?? "上传失败");
      }
      const payload = (await response.json()) as { asset: MediaAsset };
      if (!payload.asset?.file_url) {
        throw new Error("返回数据缺少文件地址");
      }
      emitAssetsChanged(documentId, payload.asset);
      return {
        assetId: payload.asset.id,
        fileUrl: payload.asset.file_url,
        thumbnailUrl: payload.asset.thumbnail_url,
        assetType: payload.asset.asset_type,
        fileName: payload.asset.file_name,
        fileSize: payload.asset.file_size,
        mimeType: payload.asset.mime_type,
      } satisfies MediaSelection;
    },
    [documentId, workspaceId],
  );

  const handleUploadMany = useCallback(
    async (files: File[]) => {
      if (files.length === 0) return;
      setUploading(true);
      setError(null);
      try {
        for (const file of files) {
          const selection = await uploadOne(file);
          onSelect(selection);
        }
        onClose();
      } catch (err) {
        setError((err as Error).message);
      } finally {
        setUploading(false);
      }
    },
    [onClose, onSelect, uploadOne],
  );

  const onDrop = useCallback(
    (acceptedFiles: File[]) => {
      if (acceptedFiles.length === 0) return;
      void handleUploadMany(multiple ? acceptedFiles : [acceptedFiles[0]]);
    },
    [handleUploadMany, multiple],
  );

  const acceptConfig = MEDIA_ACCEPTS[mediaType];

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    accept: acceptConfig ?? undefined,
    multiple,
  });

  const handleLinkSubmit = async () => {
    if (!linkUrl.trim()) return;
    try {
      const targetUrl = linkUrl.trim();
      const response = await fetch("/api/media/assets", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          workspaceId,
          documentId,
          fileUrl: targetUrl,
          thumbnailUrl: targetUrl,
          assetType: mediaType,
          fileName: guessFileNameFromUrl(targetUrl),
        }),
      });
      if (!response.ok) {
        const payload = await response.json().catch(() => null);
        throw new Error(payload?.error ?? "保存失败");
      }
      const payload = (await response.json()) as { asset: MediaAsset };
      if (!payload.asset?.file_url) {
        throw new Error("缺少图片地址");
      }
      emitAssetsChanged(documentId, payload.asset);
      onSelect({
        assetId: payload.asset.id,
        fileUrl: payload.asset.file_url,
        thumbnailUrl: payload.asset.thumbnail_url,
        assetType: payload.asset.asset_type,
        fileName: payload.asset.file_name,
        fileSize: payload.asset.file_size,
        mimeType: payload.asset.mime_type,
      });
      setLinkUrl("");
      onClose();
    } catch (err) {
      setError((err as Error).message);
    }
  };

  const renderRecent = () => {
    if (recentLoading) {
      return <div className="py-8 text-center text-sm text-gray-500">加载最近上传中...</div>;
    }
    if (recent.length === 0) {
      return <div className="py-8 text-center text-sm text-gray-400">暂无最近上传的{MEDIA_TITLES[mediaType].replace("选择", "")}</div>;
    }
    return (
      <div className="grid grid-cols-3 gap-3">
        {recent.map((asset) => (
          <button
            type="button"
            key={asset.id}
            className="rounded-xl border border-gray-200 bg-white p-2 text-left shadow-sm transition hover:border-[#2563eb]"
            onClick={() => {
              if (!asset.file_url) return;
              onSelect({
                assetId: asset.id,
                fileUrl: asset.file_url,
                thumbnailUrl: asset.thumbnail_url,
                assetType: asset.asset_type,
                fileName: asset.file_name,
                fileSize: asset.file_size,
                mimeType: asset.mime_type,
              });
              onClose();
            }}
          >
            {mediaType === "image" ? (
              <img
                src={asset.thumbnail_url ?? asset.file_url ?? ""}
                alt={asset.asset_type}
                className="h-32 w-full rounded-lg object-cover"
              />
            ) : (
              <div className="flex h-32 flex-col items-start justify-center gap-1 rounded-lg bg-gray-50 px-3">
                <p className="text-sm font-medium text-gray-700">{asset.file_name ?? "未命名资源"}</p>
                {asset.file_size ? <p className="text-xs text-gray-500">{formatBytes(asset.file_size)}</p> : null}
              </div>
            )}
            <p className="mt-2 truncate text-xs text-gray-500">
              {asset.asset_type === "icon" ? "动态图标" : MEDIA_TITLES[mediaType].replace("选择", "")}
            </p>
          </button>
        ))}
      </div>
    );
  };

  const renderIcons = () => (
    <div className="grid grid-cols-2 gap-3">
      {ICON_PRESETS.map((icon) => (
        <button
          key={icon.id}
          type="button"
          className="flex flex-col items-center rounded-xl border border-dashed border-gray-200 p-3 text-sm text-gray-600 transition hover:border-[#2563eb]"
          onClick={() => {
            onSelect({
              assetId: `icon-${icon.id}`,
              fileUrl: icon.url,
              thumbnailUrl: icon.url,
              assetType: "icon",
            });
            onClose();
          }}
        >
          <img src={icon.url} alt={icon.label} className="h-24 w-24 rounded-lg object-cover" />
          <span className="mt-2 text-xs">{icon.label}</span>
        </button>
      ))}
    </div>
  );

  const helperText = useMemo(() => {
    const label = MEDIA_TITLES[mediaType].replace("选择", "");
    switch (tab) {
      case "upload":
        return multiple
          ? `支持拖拽或点击上传${label}（可多选），单个文件不超过 200MB`
          : `支持拖拽或点击上传${label}，单个文件不超过 200MB`;
      case "recent":
        return `最近 12 个${label}，支持一键选取`;
      case "link":
        return `输入${label}直链或 CDN 地址`;
      case "icon":
        return "选择 Wolai 常用动态图标";
      default:
        return "";
    }
  }, [mediaType, multiple, tab]);

  return (
    <Dialog open={open} onOpenChange={(next) => !next && onClose()}>
      <DialogContent className="max-w-3xl">
        <DialogHeader className="text-left">
          <DialogTitle>{MEDIA_TITLES[mediaType]}</DialogTitle>
          <DialogDescription>{helperText}</DialogDescription>
        </DialogHeader>
        {error && <div className="rounded-md bg-red-50 px-3 py-2 text-sm text-red-600">{error}</div>}
        <Tabs value={tab} onValueChange={(value) => setTab(value as PickerTab)}>
          <TabsList className="mb-4">
            {availableTabs.map((tabKey) => (
              <TabsTrigger key={tabKey} value={tabKey}>
                {TAB_LABELS[tabKey]}
              </TabsTrigger>
            ))}
          </TabsList>
          {availableTabs.includes("upload") && (
            <TabsContent value="upload">
              <div
                {...getRootProps()}
                className={cn(
                  "flex h-48 cursor-pointer flex-col items-center justify-center rounded-2xl border-2 border-dashed border-gray-300 text-sm text-gray-500",
                  isDragActive && "border-[#2563eb] bg-[#f5f7ff]",
                )}
              >
                <input {...getInputProps()} />
                {uploading ? "上传中..." : "拖拽文件到此处，或点击选择文件"}
              </div>
            </TabsContent>
          )}
          {availableTabs.includes("recent") && (
            <TabsContent value="recent">
              <div className="mb-2 flex items-center justify-between text-sm">
                <span className="text-gray-500">最近上传的{MEDIA_TITLES[mediaType].replace("选择", "")}</span>
                <Button type="button" variant="ghost" size="sm" onClick={() => void fetchRecent()}>
                  刷新
                </Button>
              </div>
              {renderRecent()}
            </TabsContent>
          )}
          {availableTabs.includes("link") && (
            <TabsContent value="link">
              <div className="flex gap-2">
                <Input
                  value={linkUrl}
                  onChange={(event) => setLinkUrl(event.target.value)}
                  placeholder={`输入${MEDIA_TITLES[mediaType].replace("选择", "")}链接，例如 https://example.com/file`}
                />
                <Button type="button" onClick={() => void handleLinkSubmit()}>
                  插入
                </Button>
              </div>
            </TabsContent>
          )}
          {availableTabs.includes("icon") && <TabsContent value="icon">{renderIcons()}</TabsContent>}
        </Tabs>
      </DialogContent>
    </Dialog>
  );
}
