import { useEffect, useRef, useState } from 'react';

import { markAttachmentViewed } from '@chat-app/shared/chat';

import { supabase } from '../lib/supabase';
import { EyeOffIcon, LockIcon } from './icons';

interface Props {
  attachmentId: string;
  /** Already-viewed timestamp from the DB row. Renders tombstone immediately. */
  viewedAt: string | null;
  /** True iff the local user is the sender — they don't burn the view. */
  isSender: boolean;
  /** Decrypted image source; only fetched/displayed inside the lightbox. */
  src: string;
}

// Three states:
//   1. viewedAt is null AND user is recipient → blurred lock card. Press-and-
//      hold reveals the image fullscreen; release closes it AND fires the
//      mark-viewed RPC.
//   2. viewedAt is set → tombstone "Angesehen am …".
//   3. user is sender → normal image, tombstone update appears once recipient
//      burns it.
//
// While revealed, the renderer window enables content-protection
// (`win.setContentProtection(true)`) so OS-level screen capture (OBS, Win/Cmd
// snipping tools, screen recorders) sees a black/empty surface. Re-enabled
// on release / unmount.
export function ViewOnceImage({ attachmentId, viewedAt, isSender, src }: Props) {
  const [revealedAt, setRevealedAt] = useState<string | null>(viewedAt);
  const [revealing, setRevealing] = useState(false);
  const burnedRef = useRef(false);
  const holdingRef = useRef(false);

  const burned = revealedAt !== null;

  // Tear down screen-capture protection if the component unmounts mid-reveal.
  useEffect(() => {
    return () => {
      if (revealing || holdingRef.current) {
        void window.electronAPI?.setContentProtection?.(false).catch(() => {});
      }
    };
  }, [revealing]);

  if (burned && !isSender) {
    return (
      <div className="flex h-32 w-48 items-center justify-center rounded-lg border border-dashed border-line bg-surface-3 text-xs text-fg-muted">
        <EyeOffIcon className="mr-2 h-4 w-4" />
        Angesehen am {new Date(revealedAt).toLocaleString()}
      </div>
    );
  }

  if (isSender) {
    return (
      <div className="relative">
        <img src={src} alt="" className="max-h-72 rounded-lg" />
        <span className="absolute left-2 top-2 inline-flex items-center gap-1 rounded-full bg-black/60 px-2 py-0.5 text-[10px] font-semibold text-white">
          <EyeOffIcon className="h-3 w-3" /> Einmal ansehen
        </span>
        {burned && (
          <span className="absolute right-2 bottom-2 rounded-full bg-emerald-500/80 px-2 py-0.5 text-[10px] font-semibold text-white">
            Angesehen
          </span>
        )}
      </div>
    );
  }

  const startReveal = async (): Promise<void> => {
    if (burnedRef.current) return;
    burnedRef.current = true;
    holdingRef.current = true;
    try {
      await window.electronAPI?.setContentProtection?.(true);
    } catch (err) {
      console.warn('setContentProtection enable failed', err);
    }
    // The user may have released during the await. If so, skip showing the
    // dialog and run the close-path directly so we don't leave the renderer
    // in protected mode with no visible UI.
    if (!holdingRef.current) {
      // User released during the IPC await — endReveal already fired and is
      // responsible for teardown (setContentProtection(false) + mark-viewed).
      // Skipping teardown here avoids a duplicate markAttachmentViewed RPC.
      return;
    }
    setRevealing(true);
  };

  const endReveal = async (): Promise<void> => {
    if (!holdingRef.current && !revealing) return;
    holdingRef.current = false;
    if (revealing) setRevealing(false);
    await teardownReveal();
  };

  const teardownReveal = async (): Promise<void> => {
    try {
      await window.electronAPI?.setContentProtection?.(false);
    } catch (err) {
      console.warn('setContentProtection disable failed', err);
    }
    try {
      const res = await markAttachmentViewed(supabase, attachmentId);
      if (res.viewedAt) setRevealedAt(res.viewedAt);
    } catch (err) {
      console.warn('mark-viewed failed', err);
      burnedRef.current = false;
    }
  };

  return (
    <>
      <button
        type="button"
        onPointerDown={() => void startReveal()}
        onPointerUp={() => void endReveal()}
        onPointerLeave={() => void endReveal()}
        onPointerCancel={() => void endReveal()}
        className="relative flex h-48 w-64 cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border border-line bg-surface-3 text-fg-muted hover:border-accent/40 select-none"
      >
        <LockIcon className="h-6 w-6 text-accent" />
        <span className="text-xs font-medium">Gedrückt halten zum Ansehen</span>
      </button>
      {revealing && (
        <div
          role="dialog"
          aria-modal="true"
          aria-label="Einmal-ansehen Bild"
          className="fixed inset-0 z-50 flex items-center justify-center bg-black/95 p-6"
        >
          <img
            src={src}
            alt=""
            className="max-h-full max-w-full select-none rounded-lg"
            draggable={false}
          />
          <span className="absolute bottom-6 left-1/2 -translate-x-1/2 rounded-full bg-white/10 px-3 py-1 text-xs font-semibold text-white">
            Loslassen zum Schließen — Aufnahme blockiert
          </span>
        </div>
      )}
    </>
  );
}
