"use client";

import { useEffect, useId, useRef, useState } from "react";
import {
  Upload,
  Image as ImageIcon,
  X,
  Loader2,
  Check,
  AlertCircle,
  Library,
  GripVertical,
} from "lucide-react";

interface MediaFile {
  id: string;
  name: string;
  size: number;
  url: string;
  mimeType?: string;
  createdAt?: string;
}

type Mode = "single" | "multiple";

interface BaseProps {
  name: string;
  label: string;
  help?: string;
  accept?: string;
  maxSizeMB?: number;
}

interface SingleProps extends BaseProps {
  multiple?: false;
  defaultValue?: string | null;
}

interface MultiProps extends BaseProps {
  multiple: true;
  defaultValue?: string[] | null;
}

export function MediaPicker(props: SingleProps | MultiProps) {
  const mode: Mode = props.multiple ? "multiple" : "single";
  const id = useId();

  const initial: string[] =
    mode === "multiple"
      ? (props as MultiProps).defaultValue ?? []
      : (props as SingleProps).defaultValue
        ? [(props as SingleProps).defaultValue as string]
        : [];

  const [values, setValues] = useState<string[]>(initial);
  const [showLibrary, setShowLibrary] = useState(false);
  const [activeUploads, setActiveUploads] = useState<
    Array<{ id: string; name: string; progress: number; error?: string }>
  >([]);
  const [dragOver, setDragOver] = useState(false);
  const inputRef = useRef<HTMLInputElement>(null);

  // For multiple mode the hidden value is one URL per line (matches existing
  // textarea-based admin actions). For single mode it's just the URL.
  const hiddenValue =
    mode === "multiple"
      ? values.join("\n")
      : values[0] ?? "";

  function addUrl(url: string) {
    if (mode === "single") setValues([url]);
    else setValues((v) => (v.includes(url) ? v : [...v, url]));
  }

  function removeAt(i: number) {
    setValues((v) => v.filter((_, idx) => idx !== i));
  }

  function moveItem(from: number, to: number) {
    setValues((v) => {
      const copy = [...v];
      const [moved] = copy.splice(from, 1);
      copy.splice(to, 0, moved);
      return copy;
    });
  }

  async function uploadFile(file: File) {
    const maxBytes = (props.maxSizeMB ?? 10) * 1024 * 1024;
    if (file.size > maxBytes) {
      setActiveUploads((u) => [
        ...u,
        {
          id: Math.random().toString(36),
          name: file.name,
          progress: 0,
          error: `Dosya çok büyük (max ${props.maxSizeMB ?? 10} MB)`,
        },
      ]);
      return;
    }

    const uploadId = Math.random().toString(36);
    setActiveUploads((u) => [
      ...u,
      { id: uploadId, name: file.name, progress: 0 },
    ]);

    const fd = new FormData();
    fd.append("file", file);

    try {
      const url = await uploadWithProgress(fd, (pct) => {
        setActiveUploads((u) =>
          u.map((up) => (up.id === uploadId ? { ...up, progress: pct } : up)),
        );
      });
      addUrl(url);
      setActiveUploads((u) =>
        u.map((up) =>
          up.id === uploadId ? { ...up, progress: 100 } : up,
        ),
      );
      // 2 saniye sonra başarılı upload'ı listeden kaldır
      setTimeout(() => {
        setActiveUploads((u) => u.filter((up) => up.id !== uploadId));
      }, 2000);
    } catch (err) {
      const msg = err instanceof Error ? err.message : "Yükleme başarısız";
      setActiveUploads((u) =>
        u.map((up) =>
          up.id === uploadId ? { ...up, progress: 0, error: msg } : up,
        ),
      );
    }
  }

  function handleFiles(files: FileList | null) {
    if (!files) return;
    const arr = Array.from(files);
    if (mode === "single") {
      uploadFile(arr[0]);
    } else {
      arr.forEach(uploadFile);
    }
  }

  return (
    <div>
      <div className="flex items-center justify-between">
        <label htmlFor={id} className="text-sm font-medium text-[var(--navy)]">
          {props.label}
        </label>
        <button
          type="button"
          onClick={() => setShowLibrary(true)}
          className="inline-flex items-center gap-1 text-xs font-medium text-[var(--sky-600)] hover:text-[var(--navy)]"
        >
          <Library className="size-3.5" />
          Kütüphaneden seç
        </button>
      </div>

      <input type="hidden" name={props.name} value={hiddenValue} />

      {/* Drop zone */}
      <div
        onDragOver={(e) => {
          e.preventDefault();
          setDragOver(true);
        }}
        onDragLeave={() => setDragOver(false)}
        onDrop={(e) => {
          e.preventDefault();
          setDragOver(false);
          handleFiles(e.dataTransfer.files);
        }}
        onClick={() => inputRef.current?.click()}
        role="button"
        tabIndex={0}
        onKeyDown={(e) => {
          if (e.key === "Enter" || e.key === " ") {
            e.preventDefault();
            inputRef.current?.click();
          }
        }}
        className={`mt-1.5 flex cursor-pointer flex-col items-center justify-center gap-2 rounded-xl border-2 border-dashed bg-white p-6 text-center transition ${
          dragOver
            ? "border-[var(--sky)] bg-[var(--sky-50)]"
            : "border-[var(--border)] hover:border-[var(--sky)]"
        }`}
      >
        <input
          id={id}
          ref={inputRef}
          type="file"
          accept={props.accept ?? "image/*"}
          multiple={mode === "multiple"}
          onChange={(e) => {
            handleFiles(e.target.files);
            e.target.value = "";
          }}
          className="hidden"
        />
        <Upload className="size-7 text-[var(--sky-600)]" />
        <div>
          <p className="text-sm font-medium text-[var(--navy)]">
            {mode === "multiple"
              ? "Sürükle-bırak veya dosyaları seç"
              : "Sürükle-bırak veya dosya seç"}
          </p>
          <p className="mt-0.5 text-xs text-[var(--muted)]">
            PNG, JPG, WEBP, SVG • max {props.maxSizeMB ?? 10} MB
          </p>
        </div>
      </div>

      {/* Active uploads */}
      {activeUploads.length > 0 && (
        <div className="mt-3 space-y-2">
          {activeUploads.map((u) => (
            <div
              key={u.id}
              className="rounded-lg border border-[var(--border)] bg-white p-3"
            >
              <div className="flex items-center justify-between gap-2">
                <div className="flex min-w-0 items-center gap-2">
                  {u.error ? (
                    <AlertCircle className="size-4 shrink-0 text-red-500" />
                  ) : u.progress === 100 ? (
                    <Check className="size-4 shrink-0 text-green-600" />
                  ) : (
                    <Loader2 className="size-4 shrink-0 animate-spin text-[var(--sky-600)]" />
                  )}
                  <span className="truncate text-xs font-medium text-[var(--navy)]">
                    {u.name}
                  </span>
                </div>
                <span
                  className={`shrink-0 text-xs ${
                    u.error
                      ? "text-red-600"
                      : u.progress === 100
                        ? "text-green-600"
                        : "text-[var(--muted)]"
                  }`}
                >
                  {u.error ? "Hata" : `${u.progress}%`}
                </span>
              </div>
              {u.error ? (
                <p className="mt-1 text-xs text-red-600">{u.error}</p>
              ) : (
                <div className="mt-2 h-1.5 overflow-hidden rounded-full bg-[var(--navy-50)]">
                  <div
                    className={`h-full rounded-full transition-all ${
                      u.progress === 100
                        ? "bg-green-500"
                        : "bg-[var(--sky)]"
                    }`}
                    style={{ width: `${u.progress}%` }}
                  />
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {/* Selected previews */}
      {values.length > 0 && (
        <div
          className={`mt-3 grid gap-3 ${
            mode === "multiple" ? "grid-cols-3 sm:grid-cols-4" : "grid-cols-1"
          }`}
        >
          {values.map((url, i) => (
            <div
              key={url + i}
              className={`group relative overflow-hidden rounded-xl border border-[var(--border)] bg-white ${
                mode === "multiple" ? "aspect-square" : "aspect-video max-w-md"
              }`}
            >
              {/* eslint-disable-next-line @next/next/no-img-element */}
              <img
                src={url}
                alt=""
                className="size-full object-cover"
                loading="lazy"
              />
              <button
                type="button"
                aria-label="Kaldır"
                onClick={(e) => {
                  e.stopPropagation();
                  removeAt(i);
                }}
                className="absolute right-1.5 top-1.5 flex size-6 items-center justify-center rounded-full bg-black/60 text-white opacity-0 transition group-hover:opacity-100"
              >
                <X className="size-3.5" />
              </button>
              {mode === "multiple" && values.length > 1 && (
                <div className="absolute left-1.5 top-1.5 flex gap-1 opacity-0 transition group-hover:opacity-100">
                  {i > 0 && (
                    <button
                      type="button"
                      onClick={(e) => {
                        e.stopPropagation();
                        moveItem(i, i - 1);
                      }}
                      className="flex size-6 items-center justify-center rounded-full bg-black/60 text-white"
                      aria-label="Sola taşı"
                    >
                      <GripVertical className="size-3.5 rotate-90" />
                    </button>
                  )}
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {props.help && (
        <p className="mt-2 text-xs text-[var(--muted)]">{props.help}</p>
      )}

      {showLibrary && (
        <MediaLibraryModal
          mode={mode}
          selected={values}
          onClose={() => setShowLibrary(false)}
          onPick={(url) => {
            addUrl(url);
            if (mode === "single") setShowLibrary(false);
          }}
        />
      )}
    </div>
  );
}

function uploadWithProgress(
  fd: FormData,
  onProgress: (pct: number) => void,
): Promise<string> {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("POST", "/api/admin/media/upload");
    xhr.upload.addEventListener("progress", (e) => {
      if (e.lengthComputable) {
        onProgress(Math.round((e.loaded / e.total) * 100));
      }
    });
    xhr.onload = () => {
      try {
        const data = JSON.parse(xhr.responseText);
        if (xhr.status >= 200 && xhr.status < 300 && data.url) {
          resolve(data.url);
        } else {
          reject(new Error(data.error || `HTTP ${xhr.status}`));
        }
      } catch {
        reject(new Error("Geçersiz sunucu yanıtı"));
      }
    };
    xhr.onerror = () => reject(new Error("Ağ hatası"));
    xhr.send(fd);
  });
}

function MediaLibraryModal({
  mode,
  selected,
  onClose,
  onPick,
}: {
  mode: Mode;
  selected: string[];
  onClose: () => void;
  onPick: (url: string) => void;
}) {
  const [files, setFiles] = useState<MediaFile[] | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    fetch("/api/admin/media/list")
      .then((r) => r.json())
      .then((data) => {
        if (data.error) setError(data.error);
        else setFiles(data.files || []);
      })
      .catch(() => setError("Liste yüklenemedi"));
  }, []);

  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4"
      onClick={onClose}
    >
      <div
        className="flex max-h-[80vh] w-full max-w-4xl flex-col rounded-2xl bg-white shadow-2xl"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="flex items-center justify-between border-b border-[var(--border)] p-5">
          <div>
            <h3 className="text-base font-semibold text-[var(--navy)]">
              Medya kütüphanesi
            </h3>
            <p className="mt-1 text-xs text-[var(--muted)]">
              {mode === "multiple"
                ? "Birden fazla görsel seçebilirsiniz"
                : "Bir görsel seçin"}
            </p>
          </div>
          <button
            type="button"
            aria-label="Kapat"
            onClick={onClose}
            className="rounded-md p-1 text-[var(--muted)] hover:bg-[var(--navy-50)] hover:text-[var(--navy)]"
          >
            <X className="size-5" />
          </button>
        </div>

        <div className="flex-1 overflow-y-auto p-5">
          {error && (
            <p className="rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-800">
              {error}
            </p>
          )}
          {!files && !error && (
            <div className="flex items-center justify-center py-12 text-[var(--muted)]">
              <Loader2 className="size-5 animate-spin" />
            </div>
          )}
          {files && files.length === 0 && (
            <div className="rounded-xl border border-dashed border-[var(--border)] p-12 text-center text-sm text-[var(--muted)]">
              <ImageIcon className="mx-auto mb-3 size-8 opacity-40" />
              Kütüphanede görsel yok. Önce yükleyin.
            </div>
          )}
          {files && files.length > 0 && (
            <div className="grid grid-cols-3 gap-3 sm:grid-cols-4 lg:grid-cols-5">
              {files.map((f) => {
                const isSelected = selected.includes(f.url);
                return (
                  <button
                    key={f.id}
                    type="button"
                    onClick={() => onPick(f.url)}
                    className={`group relative aspect-square overflow-hidden rounded-xl border-2 bg-white transition ${
                      isSelected
                        ? "border-[var(--navy)] ring-2 ring-[var(--sky)]/30"
                        : "border-[var(--border)] hover:border-[var(--sky)]"
                    }`}
                  >
                    {/* eslint-disable-next-line @next/next/no-img-element */}
                    <img
                      src={f.url}
                      alt={f.name}
                      className="size-full object-cover"
                      loading="lazy"
                    />
                    {isSelected && (
                      <div className="absolute right-1.5 top-1.5 flex size-5 items-center justify-center rounded-full bg-[var(--navy)] text-white">
                        <Check className="size-3" />
                      </div>
                    )}
                    <div className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/70 to-transparent p-1.5 opacity-0 transition group-hover:opacity-100">
                      <p className="truncate text-[10px] text-white">{f.name}</p>
                    </div>
                  </button>
                );
              })}
            </div>
          )}
        </div>

        <div className="border-t border-[var(--border)] bg-[var(--navy-50)]/40 px-5 py-3 text-right">
          <button
            type="button"
            onClick={onClose}
            className="rounded-full bg-[var(--navy)] px-5 py-2 text-xs font-medium text-white hover:bg-[var(--navy-700)]"
          >
            Tamam
          </button>
        </div>
      </div>
    </div>
  );
}
