import { useState } from "react";
import { useTranslation } from "react-i18next";
import { CircleNotch, DownloadSimple } from "@phosphor-icons/react";
import StorageFiles from "@/models/files";
import showToast from "@/utils/toast";
import { humanFileSize } from "@/utils/numbers";

// File extension → display badge/colors. Lifted out of RunDetailPage with
// the file card itself; nothing else uses this map so it lives here.
const FILE_DISPLAY_MAP = {
  pptx: {
    badge: "PPT",
    bg: "bg-orange-100",
    text: "text-orange-800",
    label: (t) => t("scheduledJobs.file.types.powerpoint"),
  },
  ppt: {
    badge: "PPT",
    bg: "bg-orange-100",
    text: "text-orange-800",
    label: (t) => t("scheduledJobs.file.types.powerpoint"),
  },
  pdf: {
    badge: "PDF",
    bg: "bg-red-100",
    text: "text-red-800",
    label: (t) => t("scheduledJobs.file.types.pdf"),
  },
  doc: {
    badge: "DOC",
    bg: "bg-blue-100",
    text: "text-blue-800",
    label: (t) => t("scheduledJobs.file.types.word"),
  },
  docx: {
    badge: "DOC",
    bg: "bg-blue-100",
    text: "text-blue-800",
    label: (t) => t("scheduledJobs.file.types.word"),
  },
  xls: {
    badge: "XLS",
    bg: "bg-green-100",
    text: "text-green-800",
    label: (t) => t("scheduledJobs.file.types.spreadsheet"),
  },
  xlsx: {
    badge: "XLS",
    bg: "bg-green-100",
    text: "text-green-800",
    label: (t) => t("scheduledJobs.file.types.spreadsheet"),
  },
  csv: {
    badge: "CSV",
    bg: "bg-green-100",
    text: "text-green-800",
    label: (t) => t("scheduledJobs.file.types.spreadsheet"),
  },
  default: {
    badge: "FILE",
    bg: "bg-zinc-200",
    text: "text-zinc-800",
    label: (t) => t("scheduledJobs.file.types.generic"),
  },
};

function getFileDisplayInfo(filename, t) {
  const extension = filename?.split(".")?.pop()?.toLowerCase() ?? "txt";
  const fileDisplayInfo =
    FILE_DISPLAY_MAP[extension] || FILE_DISPLAY_MAP.default;
  return {
    ...fileDisplayInfo,
    type: fileDisplayInfo.label(t),
  };
}

// Card representing a file generated by a job run. Streams the file from
// the storage API on download via dynamic import of file-saver.
export default function GeneratedFileCard({ file }) {
  const { t } = useTranslation();
  const [downloading, setDownloading] = useState(false);
  const { badge, bg, text, type } = getFileDisplayInfo(file.filename, t);

  const handleDownload = async () => {
    if (downloading || !file.storageFilename) return;
    setDownloading(true);
    try {
      const blob = await StorageFiles.download(file.storageFilename);
      if (!blob) throw new Error("Failed to download file");
      const { saveAs } = await import("file-saver");
      saveAs(blob, file.filename || file.storageFilename);
    } catch {
      showToast(t("scheduledJobs.file.downloadFailed"), "error");
    } finally {
      setDownloading(false);
    }
  };

  return (
    <div className="flex items-center justify-between bg-zinc-800 light:bg-slate-100 rounded-lg p-3">
      <div className="flex items-center gap-3 min-w-0">
        <div
          className={`${bg} ${text} rounded-lg flex items-center justify-center shrink-0 h-10 w-10 text-xs font-semibold`}
        >
          {badge}
        </div>
        <div className="flex flex-col min-w-0">
          <p className="text-sm text-white light:text-slate-950 truncate">
            {file.filename || t("scheduledJobs.file.unknown")}
          </p>
          <p className="text-sm text-zinc-400 light:text-slate-600">
            {humanFileSize(file.fileSize, true, 1)}
            {file.fileSize && type ? " · " : ""}
            {type}
          </p>
        </div>
      </div>
      <button
        type="button"
        onClick={handleDownload}
        disabled={downloading}
        title={t("scheduledJobs.file.download")}
        aria-label={t("scheduledJobs.file.download")}
        className="border-none text-zinc-400 light:text-slate-600 hover:text-zinc-50 light:hover:text-slate-950 transition-colors shrink-0 ml-4 disabled:opacity-50"
      >
        {downloading ? (
          <CircleNotch size={16} weight="bold" className="animate-spin" />
        ) : (
          <DownloadSimple size={16} weight="bold" />
        )}
      </button>
    </div>
  );
}
