"use client";

import { useMutation, useQuery } from "@tanstack/react-query";
import clsx from "clsx";
import dayjs from "dayjs";
import { AudioLines, LoaderCircle, Search, Trash2, UploadCloud, Video } from "lucide-react";
import { useMemo, useState } from "react";

import { api, ApiError } from "@/lib/api";
import type { AssetItem } from "@/lib/types";

type MediaType = "image" | "video" | "audio";

const mediaTypes = [
  { value: "image", label: "图片", accept: "image/*" },
  { value: "video", label: "视频", accept: "video/*" },
  { value: "audio", label: "音频", accept: "audio/*" },
] as const satisfies Array<{
  value: MediaType;
  label: string;
  accept: string;
}>;

function formatBytes(fileSize: number) {
  if (fileSize < 1024) {
    return `${fileSize} B`;
  }
  if (fileSize < 1024 * 1024) {
    return `${Math.round(fileSize / 1024)} KB`;
  }
  return `${(fileSize / 1024 / 1024).toFixed(1)} MB`;
}

function getErrorMessage(error: unknown, fallback: string) {
  return error instanceof ApiError ? error.message : fallback;
}

export default function AssetsPage() {
  const [mediaType, setMediaType] = useState<MediaType>("image");
  const [libraryType, setLibraryType] = useState<"all" | MediaType>("all");
  const [keyword, setKeyword] = useState("");
  const [uploadFile, setUploadFile] = useState<File | null>(null);
  const [feedback, setFeedback] = useState<{
    tone: "success" | "error";
    text: string;
  } | null>(null);

  const assetsQuery = useQuery({
    queryKey: ["asset-list"],
    queryFn: () => api.get<AssetItem[]>("/api/v1/assets"),
  });

  const uploadMutation = useMutation({
    mutationFn: async () => {
      if (!uploadFile) {
        throw new Error("请先选择文件");
      }

      const formData = new FormData();
      formData.append("file", uploadFile);
      formData.append("mediaType", mediaType);
      return api.post<AssetItem>("/api/v1/assets", formData);
    },
    onSuccess(asset) {
      setFeedback({
        tone: "success",
        text: `素材 ${asset.originalFilename} 上传成功。`,
      });
      setUploadFile(null);
      void assetsQuery.refetch();
    },
    onError(error) {
      setFeedback({
        tone: "error",
        text: getErrorMessage(error, "素材上传失败"),
      });
    },
  });

  const deleteMutation = useMutation({
    mutationFn: (assetId: number) => api.del(`/api/v1/assets/${assetId}`),
    onSuccess: () => {
      setFeedback({
        tone: "success",
        text: "素材已删除。",
      });
      void assetsQuery.refetch();
    },
    onError(error) {
      setFeedback({
        tone: "error",
        text: getErrorMessage(error, "素材删除失败"),
      });
    },
  });

  const filteredAssets = useMemo(() => {
    let items = [...(assetsQuery.data ?? [])].sort(
      (left, right) =>
        dayjs(right.createdAt).valueOf() - dayjs(left.createdAt).valueOf(),
    );

    if (libraryType !== "all") {
      items = items.filter((asset) => asset.mediaType === libraryType);
    }

    if (keyword.trim()) {
      const loweredKeyword = keyword.trim().toLowerCase();
      items = items.filter((asset) =>
        [asset.originalFilename, asset.assetNo]
          .filter(Boolean)
          .some((field) => field.toLowerCase().includes(loweredKeyword)),
      );
    }

    return items;
  }, [assetsQuery.data, keyword, libraryType]);

  return (
    <div className="panel asset-management-shell">
      <div className="workbench-header">
        <div>
          <span className="header-kicker">Asset Center</span>
          <h3>独立素材管理</h3>
          <p className="muted">
            适合批量上传和清理素材；工作台里也能直接引用这些素材。
          </p>
        </div>
        <span className="mini-note">总素材数 {assetsQuery.data?.length ?? 0}</span>
      </div>

      <div className="asset-upload-panel">
        <div className="toolbar">
          <div className="segmented-group">
            {mediaTypes.map((item) => (
              <button
                className={clsx("segmented-button", {
                  active: mediaType === item.value,
                })}
                key={item.value}
                onClick={() => setMediaType(item.value)}
                type="button"
              >
                {item.label}
              </button>
            ))}
          </div>
          <span className="mini-note">选择类型后再上传，文件会按类型归档</span>
        </div>

        <div className="upload-row">
          <label className="file-picker">
            <input
              accept={mediaTypes.find((item) => item.value === mediaType)?.accept}
              onChange={(event) => setUploadFile(event.target.files?.[0] ?? null)}
              type="file"
            />
            <UploadCloud size={18} />
            <span>{uploadFile?.name ?? "选择一个素材文件"}</span>
          </label>
          <button
            className="primary-button"
            disabled={!uploadFile || uploadMutation.isPending}
            onClick={() => uploadMutation.mutate()}
            type="button"
          >
            {uploadMutation.isPending ? (
              <>
                <LoaderCircle className="spin" size={16} />
                上传中
              </>
            ) : (
              <>
                <UploadCloud size={16} />
                上传素材
              </>
            )}
          </button>
        </div>
      </div>

      <div className="library-toolbar">
        <div className="segmented-group">
          <button
            className={clsx("segmented-button", {
              active: libraryType === "all",
            })}
            onClick={() => setLibraryType("all")}
            type="button"
          >
            全部
          </button>
          {mediaTypes.map((item) => (
            <button
              className={clsx("segmented-button", {
                active: libraryType === item.value,
              })}
              key={item.value}
              onClick={() => setLibraryType(item.value)}
              type="button"
            >
              {item.label}
            </button>
          ))}
        </div>

        <label className="library-search">
          <Search size={16} />
          <input
            onChange={(event) => setKeyword(event.target.value)}
            placeholder="搜索文件名 / asset id"
            value={keyword}
          />
        </label>
      </div>

      {feedback ? (
        <div
          className={clsx("inline-feedback", {
            "is-success": feedback.tone === "success",
            "is-error": feedback.tone === "error",
          })}
        >
          {feedback.text}
        </div>
      ) : null}

      <div className="asset-gallery">
        {filteredAssets.length ? (
          filteredAssets.map((asset) => (
            <article className="asset-library-card" key={asset.id}>
              {asset.mediaType === "image" ? (
                <div
                  className="asset-thumb asset-thumb-image"
                  style={{ backgroundImage: `url(${asset.publicUrl})` }}
                >
                  <span className="asset-media-badge">图片</span>
                </div>
              ) : asset.mediaType === "video" ? (
                <div className="asset-thumb asset-thumb-video">
                  <video muted preload="metadata" src={asset.publicUrl} />
                  <span className="asset-media-badge">视频</span>
                </div>
              ) : (
                <div className="asset-thumb asset-thumb-audio">
                  <AudioLines size={22} />
                  <span>音频</span>
                </div>
              )}

              <div className="asset-card-body">
                <div className="asset-card-title-row">
                  <strong>{asset.originalFilename}</strong>
                </div>
                <div className="asset-card-meta">
                  {asset.assetNo} · {formatBytes(asset.fileSize)}
                </div>
                <div className="asset-card-meta">
                  {dayjs(asset.createdAt).format("YYYY-MM-DD HH:mm")}
                </div>
                <div className="row">
                  <a
                    className="ghost-button compact-button"
                    href={asset.publicUrl}
                    rel="noreferrer"
                    target="_blank"
                  >
                    {asset.mediaType === "video" ? (
                      <>
                        <Video size={14} />
                        预览
                      </>
                    ) : (
                      "查看"
                    )}
                  </a>
                  <button
                    className="danger-button compact-button"
                    onClick={() => deleteMutation.mutate(asset.id)}
                    type="button"
                  >
                    <Trash2 size={14} />
                    删除
                  </button>
                </div>
              </div>
            </article>
          ))
        ) : (
          <div className="empty-state">当前没有匹配素材，先上传或调整筛选条件。</div>
        )}
      </div>
    </div>
  );
}
