"use client";

import { useState, useEffect, useCallback, useRef } from "react";
import { createPortal } from "react-dom";
import Image from "next/image";
import Link from "next/link";
import {
  Loader2,
  Plus,
  Trash2,
  GripVertical,
  Check,
} from "lucide-react";
import { adminFetch } from "@/lib/csrf";
import type { TeamMember } from "@/types/content";

type Member = TeamMember & { id: number };

export default function TeamEditorPage() {
  const [members, setMembers] = useState<Member[]>([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [saved, setSaved] = useState(false);

  const [dragIndex, setDragIndex] = useState<number | null>(null);
  const [insertAt, setInsertAt] = useState<number | null>(null);
  const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
  const [dragSize, setDragSize] = useState({ w: 0, h: 0 });
  const [grabOffset, setGrabOffset] = useState({ x: 0, y: 0 });
  const itemRefs = useRef<(HTMLDivElement | null)[]>([]);

  useEffect(() => {
    adminFetch("/api/admin/team")
      .then((r) => r.json())
      .then(setMembers)
      .finally(() => setLoading(false));
  }, []);

  const saveOrder = useCallback(async (updated: Member[]) => {
    setMembers(updated);
    setSaving(true);
    await adminFetch("/api/admin/team/reorder", {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ ids: updated.map((m) => m.id) }),
    });
    setSaving(false);
    setSaved(true);
    setTimeout(() => setSaved(false), 2000);
  }, []);

  const startDrag = useCallback(
    (clientX: number, clientY: number, index: number) => {
      const el = itemRefs.current[index];
      if (!el) return;
      const rect = el.getBoundingClientRect();
      setDragIndex(index);
      setInsertAt(index);
      setMousePos({ x: clientX, y: clientY });
      setDragSize({ w: rect.width, h: rect.height });
      setGrabOffset({ x: clientX - rect.left, y: clientY - rect.top });
    },
    []
  );

  const handleGripMouseDown = useCallback(
    (e: React.MouseEvent, index: number) => {
      e.preventDefault();
      startDrag(e.clientX, e.clientY, index);
    },
    [startDrag]
  );

  const handleCardMouseDown = useCallback(
    (e: React.MouseEvent, index: number) => {
      const tag = (e.target as HTMLElement).closest("input, textarea, select, button, a, [role='switch']");
      if (tag) return;
      e.preventDefault();

      const x = e.clientX;
      const y = e.clientY;
      const pendingIndex = index;
      let moved = false;

      function onMove(ev: MouseEvent) {
        const dx = ev.clientX - x;
        const dy = ev.clientY - y;
        if (Math.abs(dx) > 8 || Math.abs(dy) > 8) {
          moved = true;
          cleanup();
          startDrag(ev.clientX, ev.clientY, pendingIndex);
        }
      }
      function onUp() {
        cleanup();
        if (!moved) {
          window.location.href = `/admin/team/${members[pendingIndex].id}`;
        }
      }
      function cleanup() {
        window.removeEventListener("mousemove", onMove);
        window.removeEventListener("mouseup", onUp);
      }
      window.addEventListener("mousemove", onMove);
      window.addEventListener("mouseup", onUp);
    },
    [startDrag, members]
  );

  useEffect(() => {
    if (dragIndex === null) return;

    document.body.style.userSelect = "none";

    function onMouseMove(e: MouseEvent) {
      setMousePos({ x: e.clientX, y: e.clientY });

      let newInsert = members.length;
      for (let i = 0; i < members.length; i++) {
        if (i === dragIndex) continue;
        const el = itemRefs.current[i];
        if (!el) continue;
        const rect = el.getBoundingClientRect();
        const midY = rect.top + rect.height / 2;
        if (e.clientY < midY) {
          newInsert = i > dragIndex! ? i : i;
          break;
        }
      }
      setInsertAt(newInsert);
    }

    function onMouseUp() {
      setDragIndex((prevDrag) => {
        setInsertAt((prevInsert) => {
          if (prevDrag !== null && prevInsert !== null) {
            let targetIndex = prevInsert;
            if (prevDrag < targetIndex) targetIndex -= 1;
            if (prevDrag !== targetIndex) {
              const updated = [...members];
              const [moved] = updated.splice(prevDrag, 1);
              updated.splice(targetIndex, 0, moved);
              saveOrder(updated);
            }
          }
          return null;
        });
        return null;
      });
    }

    window.addEventListener("mousemove", onMouseMove);
    window.addEventListener("mouseup", onMouseUp);
    return () => {
      document.body.style.userSelect = "";
      window.removeEventListener("mousemove", onMouseMove);
      window.removeEventListener("mouseup", onMouseUp);
    };
  }, [dragIndex, members, saveOrder]);

  async function deleteMember(id: number) {
    if (!confirm("Удалить этого участника?")) return;
    await adminFetch(`/api/admin/team/${id}`, { method: "DELETE" });
    setMembers((prev) => prev.filter((m) => m.id !== id));
  }

  if (loading) {
    return (
      <div className="flex items-center gap-2 text-neutral-400">
        <Loader2 size={18} className="animate-spin" />
        Загрузка...
      </div>
    );
  }

  const draggedMember = dragIndex !== null ? members[dragIndex] : null;

  // Build the visual order: remove dragged item, insert placeholder at insertAt
  function renderList() {
    if (dragIndex === null || insertAt === null) {
      // Normal render — no drag
      return members.map((member, i) => (
        <div
          key={member.id}
          ref={(el) => { itemRefs.current[i] = el; }}
          onMouseDown={(e) => handleCardMouseDown(e, i)}
          className="flex items-center gap-4 rounded-lg border border-white/10 bg-neutral-900/50 p-3 mb-2 hover:border-white/25 hover:bg-neutral-800/50 transition-colors cursor-pointer"
        >
          <div
            className="cursor-grab active:cursor-grabbing text-neutral-500 hover:text-white transition-colors select-none"
            onMouseDown={(e) => handleGripMouseDown(e, i)}
          >
            <GripVertical size={18} />
          </div>
          <div className="relative h-12 w-12 shrink-0 overflow-hidden rounded-lg">
            <Image src={member.image} alt={member.name} fill className="object-cover" sizes="48px" />
          </div>
          <div className="flex-1 min-w-0">
            <p className="font-medium text-white truncate">{member.name}</p>
            <p className="text-sm text-neutral-400 truncate">{member.role}</p>
          </div>
          <button onClick={(e) => { e.stopPropagation(); deleteMember(member.id); }} className="rounded p-2 text-neutral-400 hover:text-red-400 transition-colors">
            <Trash2 size={16} />
          </button>
        </div>
      ));
    }

    // During drag: build list without the dragged item, with placeholder inserted
    const elements: React.ReactNode[] = [];
    let visualIndex = 0;

    // Determine where to insert placeholder relative to non-dragged items
    let placeholderPos = insertAt;
    if (insertAt > dragIndex) placeholderPos = insertAt - 1;

    for (let i = 0; i < members.length; i++) {
      if (i === dragIndex) {
        // Keep a hidden ref so midpoint detection still works
        elements.push(
          <div key={`hidden-${members[i].id}`} ref={(el) => { itemRefs.current[i] = el; }} className="hidden" />
        );
        continue;
      }

      if (visualIndex === placeholderPos) {
        elements.push(
          <div
            key="placeholder"
            className="rounded-lg border-2 border-dashed border-rose-500/50 bg-rose-500/5 mb-2"
            style={{ height: dragSize.h }}
          />
        );
      }

      const member = members[i];
      elements.push(
        <div
          key={member.id}
          ref={(el) => { itemRefs.current[i] = el; }}
          onMouseDown={(e) => handleCardMouseDown(e, i)}
          className="flex items-center gap-4 rounded-lg border border-white/10 bg-neutral-900/50 p-3 mb-2 hover:border-white/25 hover:bg-neutral-800/50 transition-colors cursor-pointer"
        >
          <div
            className="cursor-grab active:cursor-grabbing text-neutral-500 hover:text-white transition-colors select-none"
            onMouseDown={(e) => handleGripMouseDown(e, i)}
          >
            <GripVertical size={18} />
          </div>
          <div className="relative h-12 w-12 shrink-0 overflow-hidden rounded-lg">
            <Image src={member.image} alt={member.name} fill className="object-cover" sizes="48px" />
          </div>
          <div className="flex-1 min-w-0">
            <p className="font-medium text-white truncate">{member.name}</p>
            <p className="text-sm text-neutral-400 truncate">{member.role}</p>
          </div>
          <button onClick={(e) => { e.stopPropagation(); deleteMember(member.id); }} className="rounded p-2 text-neutral-400 hover:text-red-400 transition-colors">
            <Trash2 size={16} />
          </button>
        </div>
      );
      visualIndex++;
    }

    // Placeholder at the end
    if (visualIndex === placeholderPos) {
      elements.push(
        <div
          key="placeholder"
          className="rounded-lg border-2 border-dashed border-rose-500/50 bg-rose-500/5 mb-2"
          style={{ height: dragSize.h }}
        />
      );
    }

    return elements;
  }

  return (
    <div>
      <div className="flex items-center justify-between gap-4">
        <h1 className="text-2xl font-bold">Команда</h1>
        <div className="flex items-center gap-3">
          {(saving || saved) && (
            <span className="text-sm text-neutral-400 flex items-center gap-1">
              {saving ? (
                <Loader2 size={14} className="animate-spin" />
              ) : (
                <Check size={14} className="text-green-400" />
              )}
              {saving ? "Сохранение..." : "Сохранено!"}
            </span>
          )}
          <Link
            href="/admin/team/new"
            className="flex items-center gap-2 rounded-lg bg-gold px-4 py-2.5 text-sm font-medium text-black hover:opacity-90 transition-opacity"
          >
            <Plus size={16} />
            Добавить
          </Link>
        </div>
      </div>

      <div className="mt-6">
        {renderList()}
      </div>

      {/* Floating card following cursor */}
      {dragIndex !== null &&
        draggedMember &&
        createPortal(
          <div
            className="fixed z-[9999] pointer-events-none"
            style={{
              left: mousePos.x - grabOffset.x,
              top: mousePos.y - grabOffset.y,
              width: dragSize.w,
            }}
          >
            <div className="flex items-center gap-4 rounded-lg border-2 border-rose-500 bg-neutral-900 p-3 shadow-2xl shadow-rose-500/20">
              <div className="text-rose-400">
                <GripVertical size={18} />
              </div>
              <div className="relative h-12 w-12 shrink-0 overflow-hidden rounded-lg">
                <Image
                  src={draggedMember.image}
                  alt={draggedMember.name}
                  fill
                  className="object-cover"
                  sizes="48px"
                />
              </div>
              <div className="flex-1 min-w-0">
                <p className="font-medium text-white truncate">{draggedMember.name}</p>
                <p className="text-sm text-neutral-400 truncate">{draggedMember.role}</p>
              </div>
            </div>
          </div>,
          document.body
        )}
    </div>
  );
}
