import { LoaderCircle } from "lucide-react";
import { DownloadCloudIcon } from "../../icons/DownloadCloudIcon";
import { useState } from "react";
import { useI18n } from "../../../i18n";
import type { Attachment, Post } from "../../../types/post";
import { downloadAttachment } from "../utils/downloadFile";
import { fileIcon } from "../utils/fileIcon";
import { filenameWithExtension, splitFilename } from "../utils/filenameDisplay";
import { formatBytes } from "../utils/formatBytes";
import { postDisplayText } from "../utils/postText";
import { CollapsibleText } from "../CollapsibleText";
import { useToast } from "../../Toast";

function AttachmentRow({ postId, att }: { postId: string; att: Attachment }) {
  const { t } = useI18n();
  const { showToast } = useToast();
  const { Icon, color } = fileIcon({ mime: att.mime, filename: att.filename });
  const displayFilename = filenameWithExtension(att.filename, att.mime);
  const [isDownloading, setIsDownloading] = useState(false);
  const [previewFailed, setPreviewFailed] = useState(false);

  const handleDownload = async () => {
    if (isDownloading) return;
    setIsDownloading(true);
    try {
      await downloadAttachment(postId, att.id, displayFilename);
    } catch {
      showToast(t("downloadFail"), "error");
    } finally {
      setIsDownloading(false);
    }
  };

  const isImage = att.kind === "image" || att.mime.startsWith("image/");
  const previewUrl =
    att.thumbnailUrl ?? att.posterUrl ?? (isImage ? att.url : undefined);

  return (
    <div className="group flex min-h-[64px] items-center gap-3">
      {previewUrl && !previewFailed ? (
        <img
          src={previewUrl}
          alt=""
          loading="lazy"
          decoding="async"
          onError={() => setPreviewFailed(true)}
          className="h-16 w-16 shrink-0 rounded-lg object-fill"
        />
      ) : (
        <div
          className="flex h-16 w-16 shrink-0 items-center justify-center rounded-lg"
          style={{ backgroundColor: color }}
          aria-hidden="true"
        >
          <Icon className="h-9 w-9 text-white" strokeWidth={2.1} />
        </div>
      )}
      <div className="min-w-0 flex-1">
        <div
          className="flex min-w-0 items-baseline text-[15px] font-medium leading-6 text-ark-gold group-hover:text-ark-gold2"
          title={displayFilename}
        >
          {(() => {
            const { base, ext } = splitFilename(displayFilename);
            const tailChars = Math.min(4, base.length);
            const head = base.slice(0, base.length - tailChars);
            const tail = base.slice(base.length - tailChars) + ext;
            return (
              <>
                <span className="min-w-0 truncate">{head}</span>
                <span className="shrink-0 whitespace-pre">{tail}</span>
              </>
            );
          })()}
        </div>
        <div className="text-[12px] font-medium leading-[19.2px] text-[#A8A9AE]">
          {isDownloading ? t("downloading") : formatBytes(att.sizeBytes)}
        </div>
      </div>
      <button
        type="button"
        onClick={handleDownload}
        disabled={isDownloading}
        className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-[#191921] text-white transition hover:bg-[#22232D] disabled:cursor-wait"
        aria-label={
          isDownloading ? t("downloading") : `Download ${att.filename}`
        }
        aria-busy={isDownloading}
      >
        {isDownloading ? (
          <LoaderCircle className="h-5 w-5 animate-spin" strokeWidth={2.3} />
        ) : (
          <DownloadCloudIcon className="h-6 w-6" />
        )}
      </button>
    </div>
  );
}

export function FileDocBubble({ post }: { post: Post }) {
  const { lang } = useI18n();
  const text = postDisplayText(post, lang);
  return (
    <div className="flex flex-col gap-3">
      {post.attachments.map((att) => (
        <AttachmentRow key={att.id} postId={post.id} att={att} />
      ))}
      {text ? (
        <CollapsibleText className="message-stream-copyable-text select-text whitespace-pre-wrap break-words text-[15px] font-medium leading-6 text-neutral-100">
          {text}
        </CollapsibleText>
      ) : null}
    </div>
  );
}
