import { useCallback, useEffect, useRef, useState } from "react";
import {
  FileTextIcon,
  ImageIcon,
  MicIcon,
  PauseIcon,
  PlayIcon,
  XIcon,
} from "lucide-react";
import { cn } from "@/lib/utils";

export type AttachmentCardFile = {
  filename?: string;
  mediaType?: string;
  url?: string;
};

function getExtension(filename: string) {
  const dot = filename.lastIndexOf(".");
  return dot > -1 && dot < filename.length - 1
    ? filename.slice(dot + 1).toUpperCase()
    : "ARCHIVO";
}

function formatAudioTime(value: number) {
  if (!Number.isFinite(value) || value < 0) return "0:00";
  const minutes = Math.floor(value / 60);
  const seconds = Math.floor(value % 60);
  return `${minutes}:${seconds.toString().padStart(2, "0")}`;
}

function formatVoiceNoteName(filename: string) {
  const match = filename.match(/nota-de-voz-(\d+)/i);
  if (!match) return filename;

  const date = new Date(Number(match[1]));
  if (Number.isNaN(date.getTime())) return filename;

  const datePart = `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`;
  const timePart = new Intl.DateTimeFormat("en-US", {
    hour: "numeric",
    minute: "2-digit",
    hour12: true,
  }).format(date);

  return `Nota de voz ${datePart} - ${timePart}`;
}

function RemoveButton({ filename, onRemove }: { filename: string; onRemove: () => void }) {
  return (
    <button
      type="button"
      aria-label={`Quitar ${filename}`}
      onClick={onRemove}
      className="absolute right-2 top-2 z-10 grid size-7 place-items-center rounded-full border border-border/80 bg-card/95 text-muted-foreground shadow-sm transition-colors hover:bg-card hover:text-foreground"
    >
      <XIcon className="size-3.5" />
    </button>
  );
}

function AudioPlayer({ src }: { src: string }) {
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const [playing, setPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);

  useEffect(() => {
    setPlaying(false);
    setCurrentTime(0);
    setDuration(0);
  }, [src]);

  const syncDuration = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;

    if (Number.isFinite(audio.duration) && audio.duration > 0) {
      setDuration(audio.duration);
      return;
    }

    if (audio.seekable.length > 0) {
      const seekableEnd = audio.seekable.end(audio.seekable.length - 1);
      if (Number.isFinite(seekableEnd) && seekableEnd > 0) {
        setDuration(seekableEnd);
      }
    }
  }, []);

  const togglePlayback = useCallback(async () => {
    const audio = audioRef.current;
    if (!audio) return;

    if (audio.paused) {
      try {
        await audio.play();
      } catch {
        setPlaying(false);
      }
    } else {
      audio.pause();
    }
  }, []);

  const seek = useCallback((value: number) => {
    const audio = audioRef.current;
    if (!audio) return;
    audio.currentTime = value;
    setCurrentTime(value);
  }, []);

  return (
    <div className="flex w-full items-center gap-2.5">
      <audio
        ref={audioRef}
        src={src}
        preload="metadata"
        onLoadedMetadata={syncDuration}
        onLoadedData={syncDuration}
        onCanPlay={syncDuration}
        onDurationChange={syncDuration}
        onProgress={syncDuration}
        onTimeUpdate={(event) => setCurrentTime(event.currentTarget.currentTime)}
        onPlay={() => setPlaying(true)}
        onPause={() => setPlaying(false)}
        onEnded={() => setPlaying(false)}
      />
      <button
        type="button"
        onClick={() => void togglePlayback()}
        aria-label={playing ? "Pausar nota de voz" : "Reproducir nota de voz"}
        className="grid size-9 shrink-0 place-items-center rounded-full bg-primary text-primary-foreground transition-transform hover:scale-[1.03]"
      >
        {playing ? <PauseIcon className="size-4" /> : <PlayIcon className="ml-0.5 size-4" />}
      </button>
      <span className="w-9 shrink-0 text-right text-[0.68rem] tabular-nums text-foreground">
        {formatAudioTime(currentTime)}
      </span>
      <input
        type="range"
        min={0}
        max={duration || 0}
        step={0.05}
        value={Math.min(currentTime, duration || 0)}
        disabled={!duration}
        onChange={(event) => seek(Number(event.currentTarget.value))}
        aria-label="Posición de la nota de voz"
        className="voice-note-range min-w-0 flex-1 disabled:cursor-default disabled:opacity-50"
      />
      <span className="w-9 shrink-0 text-[0.68rem] tabular-nums text-muted-foreground">
        {formatAudioTime(duration)}
      </span>
    </div>
  );
}

export function AttachmentCard({
  file,
  onRemove,
  compact = false,
}: {
  file: AttachmentCardFile;
  onRemove?: () => void;
  compact?: boolean;
}) {
  const filename = file.filename?.trim() || "archivo";
  const mediaType = file.mediaType || "application/octet-stream";
  const url = file.url || "";
  const isImage = mediaType.startsWith("image/");
  const isVideo = mediaType.startsWith("video/");
  const isAudio = mediaType.startsWith("audio/");
  const extension = getExtension(filename);

  if (isImage) {
    return (
      <div
        onClick={(event) => event.stopPropagation()}
        className={cn(
          "group relative overflow-hidden rounded-xl border border-border bg-card shadow-sm",
          compact ? "w-[8.75rem] sm:w-[9.5rem]" : "w-full max-w-[18rem]",
        )}
      >
        {onRemove ? <RemoveButton filename={filename} onRemove={onRemove} /> : null}
        <a href={url} target="_blank" rel="noreferrer" className="block" title={filename}>
          <img
            src={url}
            alt={filename}
            className={cn(
              "w-full bg-secondary object-cover transition-transform duration-200 group-hover:scale-[1.015]",
              compact ? "h-20" : "max-h-56 min-h-28",
            )}
          />
          <div className="flex items-center gap-2 border-t border-border px-2.5 py-2">
            <span className="grid size-7 shrink-0 place-items-center rounded-lg bg-brand-soft text-primary">
              <ImageIcon className="size-3.5" />
            </span>
            <div className="min-w-0">
              <p className="truncate text-xs font-bold text-foreground">{filename}</p>
              <p className="text-[0.65rem] text-muted-foreground">Imagen · {extension}</p>
            </div>
          </div>
        </a>
      </div>
    );
  }

  if (isVideo) {
    return (
      <div
        onClick={(event) => event.stopPropagation()}
        className={cn(
          "relative overflow-hidden rounded-xl border border-border bg-card shadow-sm",
          compact ? "w-[12rem] sm:w-[13rem]" : "w-full max-w-[21rem]",
        )}
      >
        {onRemove ? <RemoveButton filename={filename} onRemove={onRemove} /> : null}
        <video
          src={url}
          controls
          preload="metadata"
          className={cn("w-full bg-black object-contain", compact ? "h-20" : "max-h-64")}
        >
          Tu navegador no puede reproducir este video.
        </video>
        <div className="flex items-center gap-2 border-t border-border px-2.5 py-2">
          <span className="grid size-7 shrink-0 place-items-center rounded-lg bg-brand-soft text-primary">
            <ImageIcon className="size-3.5" />
          </span>
          <div className="min-w-0">
            <p className="truncate text-xs font-bold text-foreground">{filename}</p>
            <p className="text-[0.65rem] text-muted-foreground">Video · {extension}</p>
          </div>
        </div>
      </div>
    );
  }

  if (isAudio) {
    const voiceNoteName = formatVoiceNoteName(filename);

    return (
      <div
        onClick={(event) => event.stopPropagation()}
        className={cn(
          "relative rounded-xl border border-border bg-card p-3 shadow-sm",
          compact ? "w-[20rem] max-w-[82vw]" : "w-full max-w-[34rem]",
          onRemove && "pr-11",
        )}
      >
        {onRemove ? <RemoveButton filename={filename} onRemove={onRemove} /> : null}
        <div className={cn("flex min-w-0 items-center", compact ? "gap-2" : "gap-3")}>
          <span className={cn("grid shrink-0 place-items-center rounded-xl bg-brand-soft text-primary", compact ? "size-8" : "size-10")}>
            <MicIcon className="size-4" />
          </span>
          <div className="min-w-0 flex-1">
            <p className="text-xs font-bold leading-snug text-foreground">
              {voiceNoteName}
            </p>
            <p className="mt-0.5 text-[0.65rem] text-muted-foreground">Audio · {extension}</p>
          </div>
        </div>
        <div className={cn("w-full", compact ? "mt-2" : "mt-3")}>
          <AudioPlayer src={url} />
        </div>
      </div>
    );
  }

  return (
    <div
      onClick={(event) => event.stopPropagation()}
      className={cn(
        "relative flex items-center gap-3 rounded-xl border border-border bg-card p-3 shadow-sm",
        compact ? "w-[16rem] max-w-[78vw]" : "w-full max-w-[20rem]",
        onRemove && "pr-11",
      )}
    >
      {onRemove ? <RemoveButton filename={filename} onRemove={onRemove} /> : null}
      <span className="grid size-10 shrink-0 place-items-center rounded-xl bg-secondary text-primary">
        <FileTextIcon className="size-4" />
      </span>
      <div className="min-w-0 flex-1">
        <p className="truncate text-xs font-bold text-foreground" title={filename}>
          {filename}
        </p>
        <p className="mt-0.5 text-[0.65rem] text-muted-foreground">Archivo · {extension}</p>
      </div>
      {url ? (
        <a
          href={url}
          target="_blank"
          rel="noreferrer"
          className="shrink-0 rounded-lg border border-border bg-background px-2.5 py-1.5 text-[0.68rem] font-bold text-primary transition-colors hover:bg-secondary"
        >
          Abrir
        </a>
      ) : null}
    </div>
  );
}
