"use client";

import { useState, useCallback, useEffect, useRef } from "react";
import { useRouter } from "next/navigation";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { MemberList } from "./member-list";
import { TransferOwnershipModal } from "./transfer-ownership-modal";
import { GROUP_NAME_MAX_LENGTH } from "@/lib/constants";

interface GroupData {
  group: {
    id: string;
    name: string;
    invite_code: string;
    created_by: string;
    created_at: string;
  };
  role: "admin" | "member";
}

interface Member {
  user_id: string;
  role: "admin" | "member";
  users: { display_name: string; avatar_color: string | null } | null;
}

interface MembersResponse {
  members: Member[];
  currentUserRole: "admin" | "member";
}

export function SettingsPanel({ groupId }: { groupId: string }) {
  const queryClient = useQueryClient();
  const router = useRouter();
  const [newName, setNewName] = useState("");
  const [copied, setCopied] = useState(false);
  const [transferTarget, setTransferTarget] = useState<{
    userId: string;
    displayName: string;
  } | null>(null);
  const [deleteState, setDeleteState] = useState<"idle" | "armed" | "choosing">("idle");
  const disarmTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  const arm = useCallback(() => {
    setDeleteState("armed");
    if (disarmTimer.current) clearTimeout(disarmTimer.current);
    disarmTimer.current = setTimeout(() => setDeleteState("idle"), 4000);
  }, []);

  useEffect(() => {
    return () => {
      if (disarmTimer.current) clearTimeout(disarmTimer.current);
    };
  }, []);

  const { data, isLoading, error } = useQuery<GroupData>({
    queryKey: ["groups", groupId],
    queryFn: async () => {
      const res = await fetch(`/api/groups/${groupId}`);
      if (!res.ok) throw new Error("Failed to fetch group");
      return res.json();
    },
    staleTime: 30_000,
  });

  const rename = useMutation({
    mutationFn: async (name: string) => {
      const res = await fetch(`/api/groups/${groupId}`, {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ name }),
      });
      if (!res.ok) {
        const body = await res.json();
        throw new Error(body.error || "Failed to rename");
      }
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["groups", groupId] });
      setNewName("");
    },
  });

  const regenerateCode = useMutation({
    mutationFn: async () => {
      const res = await fetch(`/api/groups/${groupId}/invite`, {
        method: "POST",
      });
      if (!res.ok) {
        const body = await res.json();
        throw new Error(body.error || "Failed to regenerate code");
      }
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["groups", groupId] });
    },
  });

  const deleteGroup = useMutation({
    mutationFn: async () => {
      const res = await fetch(`/api/groups/${groupId}`, { method: "DELETE" });
      if (!res.ok) {
        const body = await res.json();
        throw new Error(body.error || "Failed to delete group");
      }
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["groups"] });
      router.push("/");
    },
  });

  const leaveGroup = useMutation({
    mutationFn: async () => {
      const res = await fetch(`/api/groups/${groupId}/leave`, {
        method: "POST",
      });
      if (!res.ok) {
        const body = await res.json();
        throw new Error(body.error || "Failed to leave group");
      }
      return res.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["groups"] });
      router.push("/");
    },
  });

  const transferAndLeave = useMutation({
    mutationFn: async (newAdminId: string) => {
      const tRes = await fetch(`/api/groups/${groupId}/transfer`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ new_admin_id: newAdminId }),
      });
      if (!tRes.ok) {
        const body = await tRes.json();
        throw new Error(body.error || "Failed to transfer ownership");
      }
      const lRes = await fetch(`/api/groups/${groupId}/leave`, { method: "POST" });
      if (!lRes.ok) {
        const body = await lRes.json();
        throw new Error(body.error || "Failed to leave group");
      }
      return lRes.json();
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["groups"] });
      router.push("/");
    },
  });

  const membersQuery = useQuery<MembersResponse>({
    queryKey: ["groups", groupId, "members"],
    queryFn: async () => {
      const res = await fetch(`/api/groups/${groupId}/members`);
      if (!res.ok) throw new Error("Failed to fetch members");
      return res.json();
    },
    staleTime: 30_000,
  });

  const memberCount = membersQuery.data?.members.length ?? 0;
  const successors = (membersQuery.data?.members ?? []).filter((m) => m.role !== "admin");
  const isSoloAdmin = memberCount <= 1;

  const inviteCode = data?.group.invite_code;
  const handleCopyCode = useCallback(async () => {
    if (!inviteCode) return;
    try {
      await navigator.clipboard.writeText(inviteCode);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {
      // Fallback: select text for manual copy
    }
  }, [inviteCode]);

  const handleTransferRequest = useCallback((userId: string, displayName: string) => {
    setTransferTarget({ userId, displayName });
  }, []);

  if (isLoading) return <p className="text-base text-gray-500">Loading...</p>;
  if (error) return <p className="text-base text-red-500">Failed to load group</p>;
  if (!data) return null;

  const isAdmin = data.role === "admin";

  return (
    <div className="space-y-6">
      {/* Rename (admin only) */}
      {isAdmin && (
        <div>
          <h3 className="text-base font-medium mb-2">Rename List</h3>
          <form
            onSubmit={(e) => {
              e.preventDefault();
              const trimmed = newName.trim();
              if (trimmed) rename.mutate(trimmed);
            }}
            className="flex flex-col gap-2 sm:flex-row"
          >
            <input
              type="text"
              value={newName}
              onChange={(e) => setNewName(e.target.value)}
              maxLength={GROUP_NAME_MAX_LENGTH}
              placeholder={data.group.name}
              className="flex-1 rounded-md border border-gray-300 bg-transparent px-3 py-2 text-base focus:outline-none focus:ring-2 focus:ring-blue-500 dark:border-gray-700"
            />
            <button
              type="submit"
              disabled={rename.isPending || !newName.trim()}
              className="rounded-md bg-blue-600 px-4 py-2 text-base font-medium text-white hover:bg-blue-700 disabled:opacity-50"
            >
              {rename.isPending ? "Saving..." : "Save name"}
            </button>
          </form>
          {rename.error && <p className="mt-1 text-base text-red-500">{rename.error.message}</p>}
          <div className="mt-3 flex flex-wrap items-center gap-3 text-sm">
            <button
              type="button"
              onClick={handleCopyCode}
              className="text-foreground/70 underline-offset-4 hover:text-foreground hover:underline"
              aria-label="Copy invite code"
            >
              {copied ? "Code copied" : "Copy invite code"}
            </button>
            {isAdmin && (
              <button
                type="button"
                onClick={() => regenerateCode.mutate()}
                disabled={regenerateCode.isPending}
                className="text-foreground/70 underline-offset-4 hover:text-foreground hover:underline disabled:opacity-50"
                aria-label="Regenerate invite code"
              >
                {regenerateCode.isPending ? "Regenerating..." : "Regenerate invite code"}
              </button>
            )}
          </div>
          {regenerateCode.error && (
            <p className="mt-1 text-base text-red-500">{regenerateCode.error.message}</p>
          )}
        </div>
      )}
      {!isAdmin && (
        <div className="flex flex-wrap items-center gap-3 text-sm">
          <button
            type="button"
            onClick={handleCopyCode}
            className="text-foreground/70 underline-offset-4 hover:text-foreground hover:underline"
            aria-label="Copy invite code"
          >
            {copied ? "Code copied" : "Copy invite code"}
          </button>
        </div>
      )}

      {/* Members */}
      <MemberList groupId={groupId} onTransferRequest={handleTransferRequest} />

      {/* Leave / Delete */}
      <div className="border-t border-gray-200 pt-4 dark:border-gray-700">
        {isAdmin ? (
          <div className="space-y-2">
            {deleteState !== "choosing" && (
              <button
                onClick={() => {
                  if (deleteGroup.isPending || transferAndLeave.isPending) return;
                  if (deleteState === "idle") {
                    arm();
                    return;
                  }
                  // armed: second click
                  if (isSoloAdmin) {
                    deleteGroup.mutate();
                  } else {
                    setDeleteState("choosing");
                  }
                }}
                disabled={deleteGroup.isPending}
                className={`w-full rounded-md px-4 py-2 text-base font-medium text-white disabled:opacity-50 ${
                  deleteState === "armed"
                    ? "animate-shake bg-red-700 hover:bg-red-800"
                    : "bg-red-600 hover:bg-red-700"
                }`}
                aria-live="polite"
              >
                {deleteGroup.isPending
                  ? "Deleting..."
                  : deleteState === "armed"
                    ? isSoloAdmin
                      ? "Click again to permanently delete"
                      : "Click again to choose successor"
                    : "Delete List"}
              </button>
            )}

            {deleteState === "choosing" && (
              <div className="space-y-2 rounded-md border border-red-300 p-3 dark:border-red-800">
                <p className="text-base font-medium text-red-700 dark:text-red-300">
                  Choose a new admin. You will leave the list once ownership transfers.
                </p>
                {membersQuery.isLoading ? (
                  <p className="text-base text-gray-500">Loading members...</p>
                ) : successors.length === 0 ? (
                  <p className="text-base text-gray-500">No other members available.</p>
                ) : (
                  <ul className="space-y-1">
                    {successors.map((m) => (
                      <li key={m.user_id}>
                        <button
                          onClick={() => transferAndLeave.mutate(m.user_id)}
                          disabled={transferAndLeave.isPending}
                          className="flex w-full items-center gap-2 rounded-md border border-gray-200 px-3 py-2 text-base hover:bg-gray-50 disabled:opacity-50 dark:border-gray-700 dark:hover:bg-gray-800"
                        >
                          <span
                            className="inline-block h-5 w-5 rounded-full"
                            style={{ backgroundColor: m.users?.avatar_color ?? "#6b7280" }}
                            aria-hidden="true"
                          />
                          <span>{m.users?.display_name ?? "Unknown"}</span>
                        </button>
                      </li>
                    ))}
                  </ul>
                )}
                <button
                  onClick={() => setDeleteState("idle")}
                  disabled={transferAndLeave.isPending}
                  className="text-sm text-gray-600 hover:underline dark:text-gray-400"
                >
                  Cancel
                </button>
                {transferAndLeave.error && (
                  <p className="text-base text-red-500">{transferAndLeave.error.message}</p>
                )}
              </div>
            )}
            {deleteGroup.error && (
              <p className="text-base text-red-500">{deleteGroup.error.message}</p>
            )}
          </div>
        ) : (
          <div className="space-y-2">
            <button
              onClick={() => {
                if (leaveGroup.isPending) return;
                if (deleteState === "idle") {
                  arm();
                  return;
                }
                leaveGroup.mutate();
              }}
              disabled={leaveGroup.isPending}
              className={`w-full rounded-md border px-4 py-2 text-base font-medium disabled:opacity-50 ${
                deleteState === "armed"
                  ? "animate-shake border-red-500 bg-red-50 text-red-700 dark:bg-red-900/30 dark:text-red-300"
                  : "border-red-300 text-red-600 hover:bg-red-50 dark:border-red-800 dark:text-red-400 dark:hover:bg-red-900/20"
              }`}
              aria-live="polite"
            >
              {leaveGroup.isPending
                ? "Leaving..."
                : deleteState === "armed"
                  ? "Click again to confirm"
                  : "Leave List"}
            </button>
            {leaveGroup.error && (
              <p className="text-base text-red-500">{leaveGroup.error.message}</p>
            )}
          </div>
        )}
      </div>

      {/* Transfer modal */}
      {transferTarget && (
        <TransferOwnershipModal
          groupId={groupId}
          targetUserId={transferTarget.userId}
          targetDisplayName={transferTarget.displayName}
          onClose={() => setTransferTarget(null)}
        />
      )}
    </div>
  );
}
