import { useRef, useState } from "react";
import { api } from "../api/client";
import type { CreativeAsset, AssetDef } from "../types";
import styles from "./AssetUploader.module.css";

const BASE = `${import.meta.env.BASE_URL}api/v1`.replace(/\/+$/, "");

// 可展示缩略图的图片后缀
const IMAGE_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg"]);

function isImageFile(fileName: string): boolean {
  const ext = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
  return IMAGE_EXTENSIONS.has(ext);
}

interface Props {
  creativeId: string;
  assets: CreativeAsset[];
  assetDefs: { required: AssetDef[]; optional: AssetDef[] };
  onUpdated: () => void;
}

type ImportMode = "file" | "url";

export default function AssetUploader({ creativeId, assets, assetDefs, onUpdated }: Props) {
  const [mode, setMode] = useState<ImportMode>("file");
  const [uploading, setUploading] = useState(false);
  const [singleUploading, setSingleUploading] = useState<string | null>(null);
  const [url, setUrl] = useState("");
  const [uploadResult, setUploadResult] = useState<{
    files: Array<{ key: string; fileName: string; fileSize: number; valid: boolean }>;
    warnings: string[];
  } | null>(null);
  const [error, setError] = useState("");
  const [imgDims, setImgDims] = useState<Record<string, string>>({});
  const fileInputRefs = useRef<Record<string, HTMLInputElement | null>>({});

  // 读取图片实际尺寸
  function handleImgLoad(key: string, e: React.SyntheticEvent<HTMLImageElement>) {
    const img = e.currentTarget;
    setImgDims((prev) => ({ ...prev, [key]: `${img.naturalWidth}×${img.naturalHeight}` }));
  }

  // === ZIP 上传 ===
  async function handleFileUpload(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file) return;

    setUploading(true);
    setError("");
    setUploadResult(null);

    try {
      const res = await api.uploadAssets(creativeId, file);
      setUploadResult(res.data);
      onUpdated();
    } catch (err: any) {
      setError(err.message);
    } finally {
      setUploading(false);
      e.target.value = "";
    }
  }

  // === URL 导入 ===
  async function handleUrlImport() {
    if (!url.trim()) return;

    setUploading(true);
    setError("");
    setUploadResult(null);

    try {
      const res = await api.importFromUrl(creativeId, url.trim());
      setUploadResult(res.data);
      onUpdated();
    } catch (err: any) {
      setError(err.message);
    } finally {
      setUploading(false);
    }
  }

  // === 单个素材文件上传（点击替换） ===
  function handleSingleUploadClick(key: string) {
    fileInputRefs.current[key]?.click();
  }

  async function handleSingleFileChange(key: string, e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file) return;

    setSingleUploading(key);
    setError("");
    try {
      await api.uploadAssetFile(creativeId, key, file);
      onUpdated();
    } catch (err: any) {
      setError(err.message);
    } finally {
      setSingleUploading(null);
      e.target.value = "";
    }
  }

  // === 清除 ===
  async function handleClear() {
    if (!confirm("确认清除所有素材？")) return;
    try {
      await api.clearAssets(creativeId);
      setUploadResult(null);
      setUrl("");
      onUpdated();
    } catch (err: any) {
      setError(err.message);
    }
  }

  const allDefs = [...assetDefs.required, ...assetDefs.optional];
  const hasAllRequired = assetDefs.required.every((def) =>
    assets.some((a) => a.key === def.key)
  );

  // 哪些 key 是可手动替换的（optional + 图片文件，排除 special）
  const EXCLUDE_MANUAL = new Set(["special"]);
  const replaceableDefs = assetDefs.optional.filter((d) => isImageFile(d.file) && !EXCLUDE_MANUAL.has(d.key));
  const replaceableKeys = new Set(replaceableDefs.map((d) => d.key));
  // 填色素材（ZIP 导入的）与可替换素材分开
  const zipAssetDefs = allDefs.filter((d) => !replaceableKeys.has(d.key));
  const brandAssetDefs = allDefs.filter((d) => replaceableKeys.has(d.key));

  return (
    <div className={styles.wrapper}>
      {/* 模式切换 */}
      <div className={styles.tabs}>
        <button
          className={`${styles.tab} ${mode === "file" ? styles.tabActive : ""}`}
          onClick={() => setMode("file")}
        >
          上传 ZIP
        </button>
        <button
          className={`${styles.tab} ${mode === "url" ? styles.tabActive : ""}`}
          onClick={() => setMode("url")}
        >
          素材 URL
        </button>
      </div>

      {/* 文件上传 */}
      {mode === "file" && (
        <label className={styles.dropZone}>
          <input
            type="file"
            accept=".zip"
            onChange={handleFileUpload}
            disabled={uploading}
            className={styles.fileInput}
          />
          <span className={styles.dropIcon}>📦</span>
          <span className={styles.dropText}>
            {uploading ? "解压中…" : "拖拽或点击上传素材 zip"}
          </span>
          <span className={styles.dropHint}>
            包含 config.json + page.png + map.png ± special.jpeg
          </span>
        </label>
      )}

      {/* URL 导入 */}
      {mode === "url" && (
        <div className={styles.urlRow}>
          <input
            type="url"
            className={styles.urlInput}
            placeholder="https://color2.jccytech.cn/app/zh/pages/detail/6a15..."
            value={url}
            onChange={(e) => setUrl(e.target.value)}
            disabled={uploading}
          />
          <button
            onClick={handleUrlImport}
            disabled={!url.trim() || uploading}
            className={styles.urlBtn}
          >
            {uploading ? "获取中…" : "导入"}
          </button>
        </div>
      )}

      {/* 上传结果 */}
      {uploadResult && uploadResult.warnings.length > 0 && (
        <div className={styles.warnings}>
          {uploadResult.warnings.map((w, i) => (
            <p key={i}>⚠️ {w}</p>
          ))}
        </div>
      )}

      {error && <p className={styles.error}>{error}</p>}

      {/* 文件列表 */}
      <div className={styles.fileList}>
        <div className={styles.fileListHeader}>
          <span>素材文件</span>
          {assets.length > 0 && (
            <button onClick={handleClear} className={styles.clearBtn}>
              清除素材
            </button>
          )}
        </div>

        {/* 填色素材 (ZIP 导入) */}
        <div className={styles.sectionLabel}>填色素材</div>
        {zipAssetDefs.map((def) => {
          const asset = assets.find((a) => a.key === def.key);
          const isRequired = assetDefs.required.some((r) => r.key === def.key);
          const showThumb = asset && isImageFile(def.file);

          return (
            <div key={def.key} className={styles.fileItem}>
              {showThumb ? (
                <img
                  className={styles.thumb}
                  src={`${BASE}/creatives/${creativeId}/assets/${def.key}`}
                  alt={def.label}
                  onLoad={(e) => handleImgLoad(def.key, e)}
                />
              ) : (
                <span className={asset ? styles.fileOk : styles.fileMissing}>
                  {asset ? "✅" : isRequired ? "❌" : "⬜"}
                </span>
              )}
              <span className={styles.fileName}>{def.file}</span>
              <span className={styles.fileLabel}>
                {def.label} {!isRequired && !asset ? "(无)" : !isRequired ? "(选填)" : ""}
                {imgDims[def.key] && <span className={styles.dimensions}>{imgDims[def.key]}</span>}
              </span>
              {asset && (
                <span className={styles.fileSize}>
                  {(asset.fileSize / 1024).toFixed(0)} KB
                </span>
              )}
            </div>
          );
        })}

        {/* 品牌素材 (可手动替换) */}
        {brandAssetDefs.length > 0 && (
          <>
            <div className={styles.divider} />
            <div className={styles.sectionLabel}>品牌素材 · 点击可替换</div>
            {brandAssetDefs.map((def) => {
              const asset = assets.find((a) => a.key === def.key);
              const isUploading = singleUploading === def.key;

              return (
                <div
                  key={def.key}
                  className={`${styles.fileItem} ${styles.fileItemClickable}`}
                  onClick={() => handleSingleUploadClick(def.key)}
                  title="点击上传替换"
                >
                  <input
                    type="file"
                    accept={def.accept || ".png,.jpg,.jpeg"}
                    ref={(el) => { fileInputRefs.current[def.key] = el; }}
                    onChange={(e) => handleSingleFileChange(def.key, e)}
                    className={styles.fileInput}
                  />

                  {isUploading ? (
                    <span className={styles.thumbLoading}>⏳</span>
                  ) : (
                    <img
                      className={styles.thumb}
                      src={`${BASE}/creatives/${creativeId}/assets/${def.key}`}
                      alt={def.label}
                      onLoad={(e) => handleImgLoad(def.key, e)}
                    />
                  )}
                  <span className={styles.fileName}>{def.file}</span>
                  <span className={styles.fileLabel}>
                    {def.label}
                    {imgDims[def.key] && <span className={styles.dimensions}>{imgDims[def.key]}</span>}
                    {def.dimensions && (
                      <span className={styles.dimensionsHint}>建议 {def.dimensions}</span>
                    )}
                    {asset && <span className={styles.replaceHint}> 🔄</span>}
                  </span>
                  <span className={styles.fileSize}>
                    {asset
                      ? `${(asset.fileSize / 1024).toFixed(0)} KB`
                      : def.defaultFileSize
                        ? `${(def.defaultFileSize / 1024).toFixed(0)} KB`
                        : ""}
                  </span>
                </div>
              );
            })}
          </>
        )}
      </div>

      {!hasAllRequired && (
        <p className={styles.hint}>请上传包含所有必填文件的 zip 包</p>
      )}

      {!hasAllRequired && assets.length > 0 && (
        <p className={styles.hint}>请上传包含所有必填文件的 zip 包</p>
      )}
    </div>
  );
}
