import { LoaderCircle, Play } from "lucide-react";
import { useState } from "react";
import { Link } from "react-router-dom";
import { FavoriteButton } from "../favorites/FavoriteButton";
import { useI18n } from "../i18n";
import { useLocalizedPath } from "../useLocalizedPath";
import type { Attachment, Post } from "../types/post";
import { DownloadCloudIcon } from "./icons/DownloadCloudIcon";
import {
  mediaSaveKindFromAttachment,
  useSaveToAlbumGuide,
} from "./SaveToAlbumGuide";
import { useToast } from "./Toast";
import { downloadAttachment } from "./messageStream/utils/downloadFile";
import { fileIcon } from "./messageStream/utils/fileIcon";
import {
  filenameWithExtension,
  splitFilename,
} from "./messageStream/utils/filenameDisplay";
import { formatBytes } from "./messageStream/utils/formatBytes";
import { formatDateTime } from "./messageStream/utils/formatTime";
import { postDisplayText } from "./messageStream/utils/postText";
import { autolink } from "./messageStream/utils/autolink";

function LatestActions({
  post,
  attachment,
}: {
  post: Post;
  attachment?: Attachment;
}) {
  const { t } = useI18n();
  const { showToast } = useToast();
  const { showSaveToAlbumGuide } = useSaveToAlbumGuide();
  const [isDownloading, setIsDownloading] = useState(false);

  const handleDownload = async () => {
    if (!attachment || isDownloading) return;
    setIsDownloading(true);
    try {
      await downloadAttachment(post.id, attachment.id, attachment.filename, {
        sizeBytes: attachment.sizeBytes,
      });
      const mediaKind = mediaSaveKindFromAttachment(attachment);
      if (mediaKind) showSaveToAlbumGuide(mediaKind);
    } catch {
      showToast(t("downloadFail"), "error");
    } finally {
      setIsDownloading(false);
    }
  };

  return (
    <div className="relative z-20 flex shrink-0 items-center gap-2">
      <FavoriteButton resourceId={post.id} size="sm" />
      {attachment ? (
        <button
          type="button"
          onClick={(event) => {
            event.preventDefault();
            event.stopPropagation();
            void handleDownload();
          }}
          disabled={isDownloading}
          aria-label={
            isDownloading ? t("downloading") : `Download ${attachment.filename}`
          }
          aria-busy={isDownloading}
          className="relative z-20 flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-[#191921] text-white outline-none transition hover:bg-[#22232D] focus-visible:ring-2 focus-visible:ring-ark-gold/70 disabled:cursor-wait"
        >
          {isDownloading ? (
            <LoaderCircle
              className="h-4 w-4 animate-spin text-[#A8A9AE]"
              strokeWidth={2.3}
            />
          ) : (
            <DownloadCloudIcon className="h-5 w-5" />
          )}
        </button>
      ) : null}
    </div>
  );
}

function Footer({ post, attachment }: { post: Post; attachment?: Attachment }) {
  return (
    <div className="flex min-h-16 items-center justify-between gap-3 px-4 py-3">
      <time
        dateTime={post.publishedAt}
        className="shrink-0 text-[12px] font-medium leading-[19.2px] text-[#A8A9AE]"
      >
        {formatDateTime(post.publishedAt)}
      </time>
      <LatestActions post={post} attachment={attachment} />
    </div>
  );
}

function attachmentPreview(att: Attachment | undefined): string {
  if (!att) return "";
  return att.thumbnailUrl ?? att.posterUrl ?? att.thumbUrl ?? att.url ?? "";
}

function FileCard({ post, att }: { post: Post; att: Attachment }) {
  const { lang } = useI18n();
  const { Icon, color } = fileIcon({ mime: att.mime, filename: att.filename });
  const displayFilename = filenameWithExtension(att.filename, att.mime);
  const text = postDisplayText(post, lang);

  return (
    <article className="relative flex flex-col overflow-hidden rounded-2xl bg-[#272632] text-left">
      <CardLink postId={post.id} />
      <div className="flex min-h-[52px] min-w-0 items-center gap-4 px-4 pt-3">
        <div
          className="flex h-[52px] w-[52px] shrink-0 items-center justify-center rounded-full"
          style={{ backgroundColor: color }}
          aria-hidden
        >
          <Icon className="h-8 w-8 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"
            title={displayFilename}
          >
            {(() => {
              const { base, ext } = splitFilename(displayFilename);
              const tailChars = Math.min(8, 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]">
            {formatBytes(att.sizeBytes)}
          </div>
        </div>
      </div>
      <div className="whitespace-pre-wrap break-words px-4 pt-3 text-[15px] font-medium leading-6 text-white">
        {text || post.title || displayFilename}
      </div>
      <Footer post={post} attachment={att} />
    </article>
  );
}

function PillDownloadIcon() {
  return (
    <svg
      width="12"
      height="10"
      viewBox="0 0 12 10"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      aria-hidden="true"
    >
      <path
        d="M9.84528 3.61663C9.68928 1.5958 8.02426 0 6.00008 0C4.26863 0 2.78232 1.14503 2.30275 2.81502C0.934727 3.29852 0 4.6181 0 6.10918C0 8.034 1.53816 9.60013 3.42862 9.60013H9.00013C10.6544 9.60013 12.0002 8.22993 12.0002 6.54555C12.0002 5.17142 11.113 3.99191 9.84528 3.61663ZM8.0174 5.98132L6.30309 7.7268C6.21952 7.81189 6.1098 7.85465 6.00008 7.85465C5.89037 7.85465 5.78065 7.81189 5.69708 7.7268L3.98277 5.98132C3.8602 5.85652 3.82334 5.66888 3.88977 5.50568C3.9562 5.34291 4.11263 5.23644 4.28577 5.23644H5.14293V3.49096C5.14293 3.00921 5.52693 2.61822 6.00008 2.61822C6.47323 2.61822 6.85724 3.00921 6.85724 3.49096V5.23644H7.71439C7.88754 5.23644 8.04397 5.34291 8.1104 5.50568C8.17683 5.66888 8.13997 5.85652 8.0174 5.98132Z"
        fill="#A8A9AE"
      />
    </svg>
  );
}

function MediaSizeChip({ att }: { att: Attachment }) {
  return (
    <div className="absolute left-3 top-2.5 z-20 flex h-6 w-[72px] items-center overflow-hidden rounded-full bg-black text-white">
      <span className="grid h-6 w-6 shrink-0 place-items-center bg-[#545454]">
        <PillDownloadIcon />
      </span>
      <span className="flex h-4 w-12 items-center justify-center text-[10px] font-medium leading-4">
        {formatBytes(att.sizeBytes)}
      </span>
    </div>
  );
}

function MediaTile({
  att,
  showExtra,
}: {
  att: Attachment;
  showExtra?: number;
}) {
  const src = attachmentPreview(att);
  const isVideo = att.kind === "video" || att.mime.startsWith("video/");
  return (
    <div className="relative h-full w-full overflow-hidden bg-black">
      {src ? (
        <img
          src={src}
          alt=""
          className="h-full w-full object-cover"
          loading="lazy"
          decoding="async"
        />
      ) : null}
      <MediaSizeChip att={att} />
      {isVideo ? (
        <div className="absolute inset-0 grid place-items-center">
          <span className="grid h-16 w-16 place-items-center rounded-full bg-black/55 text-white backdrop-blur-sm">
            <Play className="ml-1 h-8 w-8 fill-current" />
          </span>
        </div>
      ) : null}
      {showExtra ? (
        <div className="absolute inset-0 grid place-items-center bg-black/55 text-[24px] font-bold text-white backdrop-blur-sm">
          +{showExtra}
        </div>
      ) : null}
    </div>
  );
}

function MediaGrid({ attachments }: { attachments: Attachment[] }) {
  const visible = attachments.slice(0, 4);
  const extra = Math.max(0, attachments.length - visible.length);
  if (visible.length === 0) return <div className="h-full w-full bg-black" />;
  if (visible.length === 1) return <MediaTile att={visible[0]} />;
  if (visible.length === 2) {
    return (
      <div className="grid h-full w-full grid-cols-2 gap-0">
        {visible.map((att) => (
          <MediaTile key={att.id} att={att} />
        ))}
      </div>
    );
  }
  if (visible.length === 3) {
    return (
      <div className="grid h-full w-full grid-cols-2 gap-0">
        <MediaTile att={visible[0]} />
        <div className="grid h-full grid-rows-2 gap-0">
          <MediaTile att={visible[1]} />
          <MediaTile att={visible[2]} />
        </div>
      </div>
    );
  }
  return (
    <div className="grid h-full w-full grid-cols-2 grid-rows-2 gap-0">
      {visible.map((att, index) => (
        <MediaTile
          key={att.id}
          att={att}
          showExtra={extra > 0 && index === visible.length - 1 ? extra : 0}
        />
      ))}
    </div>
  );
}

function VisualCard({ post }: { post: Post }) {
  const { lang } = useI18n();
  const att = post.attachments[0];
  const isVideo = att?.kind === "video" || att?.mime.startsWith("video/");
  const text = postDisplayText(post, lang);

  return (
    <article className="relative flex flex-col overflow-hidden rounded-2xl bg-[#272632] text-left">
      <CardLink postId={post.id} />
      <div
        className={`relative overflow-hidden bg-black ${
          isVideo ? "aspect-[416/180]" : "aspect-[416/230]"
        }`}
      >
        <MediaGrid attachments={post.attachments} />
      </div>
      {text || post.title ? (
        <div className="message-stream-copyable-text whitespace-pre-wrap break-words px-4 pt-3 text-[15px] font-medium leading-6 text-white">
          {autolink(text || post.title || "")}
        </div>
      ) : null}
      <Footer post={post} />
    </article>
  );
}

function CardLink({ postId }: { postId: string }) {
  const lp = useLocalizedPath();
  return (
    <Link
      to={lp(`/browse?post=${encodeURIComponent(postId)}`)}
      aria-label="Open post"
      className="absolute inset-0 z-10 rounded-2xl outline-none focus-visible:ring-2 focus-visible:ring-ark-gold/70"
    />
  );
}

export function LatestUpdateCard({ post }: { post: Post }) {
  const first = post.attachments[0];
  const isFile =
    !!first &&
    !(
      first.kind === "image" ||
      first.kind === "video" ||
      first.mime.startsWith("image/") ||
      first.mime.startsWith("video/")
    );
  if (isFile) return <FileCard post={post} att={first} />;
  return <VisualCard post={post} />;
}
