import { useState, useEffect, useCallback } from "react";
import { createPortal } from "react-dom";
import { FiX, FiChevronLeft, FiChevronRight, FiFile, FiDownload } from "react-icons/fi";
import type { MessageFile } from "@/api/generated/private/models/messageFile";
import { mediaUrl } from "@/utils/mediaUrl";

interface Props {
  files: readonly MessageFile[];
}

export default function ChatMediaGallery({ files }: Props) {
  const [lightboxIndex, setLightboxIndex] = useState<number | null>(null);
  const visible = files.slice(0, 4);
  const overflow = files.length - visible.length;
  const isOpen = lightboxIndex !== null;

  const prev = useCallback(
    () => setLightboxIndex((i) => (i !== null ? (i - 1 + files.length) % files.length : null)),
    [files.length],
  );
  const next = useCallback(
    () => setLightboxIndex((i) => (i !== null ? (i + 1) % files.length : null)),
    [files.length],
  );
  const close = useCallback(() => setLightboxIndex(null), []);

  useEffect(() => {
    if (!isOpen) return;
    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") close();
      if (e.key === "ArrowLeft") prev();
      if (e.key === "ArrowRight") next();
    }
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [isOpen, close, prev, next]);

  if (!files?.length) return null;

  const layoutClass = visible.length === 1 ? "grid-cols-1" : "grid-cols-2";

  return (
    <>
      <div className={`mt-2 grid ${layoutClass} gap-px overflow-hidden rounded-xl bg-brand-lines/20`}>
        {visible.map((file, i) => (
          <ChatMediaItem
            key={file.id}
            file={file}
            overflowCount={i === 3 && overflow > 0 ? overflow : 0}
            onOpen={() => setLightboxIndex(i)}
          />
        ))}
      </div>

      {isOpen &&
        createPortal(
          <div
            className="fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-sm"
            onClick={close}
          >
            <button
              type="button"
              onClick={close}
              className="absolute right-4 top-4 flex h-9 w-9 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors"
            >
              <FiX size={20} />
            </button>

            {files.length > 1 && (
              <button
                type="button"
                onClick={(e) => { e.stopPropagation(); prev(); }}
                className="absolute left-4 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors"
              >
                <FiChevronLeft size={24} />
              </button>
            )}

            <ChatLightboxContent file={files[lightboxIndex!]} />

            {files.length > 1 && (
              <button
                type="button"
                onClick={(e) => { e.stopPropagation(); next(); }}
                className="absolute right-4 flex h-10 w-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/20 transition-colors"
              >
                <FiChevronRight size={24} />
              </button>
            )}

            {files.length > 1 && (
              <div
                className="absolute bottom-5 flex items-center gap-2"
                onClick={(e) => e.stopPropagation()}
              >
                {files.map((_, i) => (
                  <button
                    key={i}
                    type="button"
                    onClick={() => setLightboxIndex(i)}
                    className={[
                      "h-2 rounded-full transition-all duration-200",
                      i === lightboxIndex ? "w-5 bg-white" : "w-2 bg-white/40 hover:bg-white/70",
                    ].join(" ")}
                  />
                ))}
              </div>
            )}
          </div>,
          document.body,
        )}
    </>
  );
}

function ChatLightboxContent({ file }: { file: MessageFile }) {
  const url = mediaUrl(file.file) ?? "";
  const type = file.media_type ?? "FILE";

  if (type === "VIDEO") {
    return (
      <video
        src={url}
        controls
        preload="none"
        className="max-h-[90vh] max-w-[90vw] rounded-xl shadow-2xl"
        onClick={(e) => e.stopPropagation()}
      />
    );
  }
  if (type === "IMAGE") {
    return (
      <img
        src={url}
        alt=""
        className="max-h-[90vh] max-w-[90vw] rounded-xl object-contain shadow-2xl select-none"
        onClick={(e) => e.stopPropagation()}
        draggable={false}
      />
    );
  }
  const filename = url.split("/").pop() ?? "soubor";
  return (
    <a
      href={url}
      download
      target="_blank"
      rel="noreferrer"
      onClick={(e) => e.stopPropagation()}
      className="flex flex-col items-center gap-4 rounded-2xl border border-white/20 bg-white/10 px-10 py-8 text-white hover:bg-white/20 transition-colors"
    >
      <FiFile size={48} />
      <span className="max-w-xs truncate text-sm">{filename}</span>
      <FiDownload size={20} className="opacity-70" />
    </a>
  );
}

function ChatMediaItem({
  file,
  onOpen,
  overflowCount = 0,
}: {
  file: MessageFile;
  onOpen: () => void;
  overflowCount?: number;
}) {
  const url = mediaUrl(file.file) ?? "";
  const type = file.media_type ?? "FILE";

  const overlay =
    overflowCount > 0 ? (
      <div
        className="absolute inset-0 flex items-center justify-center bg-black/55 cursor-pointer"
        onClick={(e) => { e.stopPropagation(); onOpen(); }}
      >
        <span className="text-2xl font-semibold text-white">+{overflowCount}</span>
      </div>
    ) : null;

  if (type === "VIDEO") {
    return (
      <div
        className="relative aspect-square w-full max-w-[200px] bg-black cursor-pointer"
        onClick={(e) => { e.stopPropagation(); onOpen(); }}
      >
        <video
          src={url}
          muted
          playsInline
          preload="metadata"
          onLoadedMetadata={(e) => { (e.target as HTMLVideoElement).currentTime = 0.001; }}
          className="h-full w-full object-cover pointer-events-none"
        />
        <div className="absolute inset-0 flex items-center justify-center bg-black/20">
          <div className="flex h-8 w-8 items-center justify-center rounded-full bg-white/20">
            <svg viewBox="0 0 24 24" fill="white" className="h-4 w-4 translate-x-0.5">
              <path d="M8 5v14l11-7z" />
            </svg>
          </div>
        </div>
        {overlay}
      </div>
    );
  }

  if (type === "IMAGE") {
    return (
      <div className="relative aspect-square w-full max-w-[200px] bg-brand-bg/60">
        <img
          src={url}
          alt=""
          className="h-full w-full cursor-zoom-in object-cover transition-opacity hover:opacity-90"
          loading="lazy"
          onClick={(e) => { e.stopPropagation(); onOpen(); }}
        />
        {overlay}
      </div>
    );
  }

  const filename = url.split("/").pop() ?? "soubor";
  return (
    <div className="relative p-1">
      <a
        href={url}
        download
        target="_blank"
        rel="noreferrer"
        onClick={(e) => e.stopPropagation()}
        className="flex items-center gap-2 rounded-lg border border-brand-lines/20 bg-brand-bgLight/30 px-2 py-1.5 hover:bg-brand-lines/10 transition-colors"
      >
        <FiFile size={18} className="shrink-0 text-brand-text/40" />
        <span className="max-w-[140px] truncate text-[11px] text-brand-text/70 leading-tight">
          {filename}
        </span>
        <FiDownload size={12} className="shrink-0 text-brand-text/30" />
      </a>
      {overlay}
    </div>
  );
}
