import { useCallback, useEffect, useState } from "react";
import { get, put, post, del } from "./api";

export interface User {
  id: string;
  username: string;
  classId: string | null;
  isActive: boolean;
  balance: string;
  xp: string;
  level: number;
  dailyStreak: number;
  settings: Record<string, unknown>;
  createdAt: string;
  updatedAt: string;
  class?: Class;
}

export interface Class {
  id: string;
  name: string;
  description: string;
  icon: string;
}

export interface Item {
  id: number;
  name: string;
  description: string;
  rarity: string;
  sellPrice: string;
  buyPrice: string;
}

export interface InventoryEntry {
  userId: string;
  itemId: number;
  quantity: string;
  item?: Item;
}

export interface UserFilters {
  search: string;
  classId: string | null;
  isActive: boolean | null;
  sortBy: "username" | "level" | "balance" | "xp";
  sortOrder: "asc" | "desc";
}

export function useUsers() {
  // User list state
  const [users, setUsers] = useState<User[]>([]);
  const [total, setTotal] = useState(0);
  const [currentPage, setCurrentPage] = useState(1);
  const [limit, setLimit] = useState(50);

  // Filters
  const [filters, setFiltersState] = useState<UserFilters>({
    search: "",
    classId: null,
    isActive: null,
    sortBy: "balance",
    sortOrder: "desc",
  });

  // Detail panel state
  const [selectedUser, setSelectedUser] = useState<User | null>(null);
  const [userDraft, setUserDraft] = useState<Partial<User> | null>(null);
  const [inventoryDraft, setInventoryDraft] = useState<InventoryEntry[]>([]);

  // Reference data
  const [classes, setClasses] = useState<Class[]>([]);
  const [items, setItems] = useState<Item[]>([]);

  // UI state
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  // Fetch users with filters and pagination
  const fetchUsers = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);

      const params = new URLSearchParams();
      if (filters.search) params.set("search", filters.search);
      if (filters.classId) params.set("classId", filters.classId);
      if (filters.isActive !== null) params.set("isActive", String(filters.isActive));
      params.set("sortBy", filters.sortBy);
      params.set("sortOrder", filters.sortOrder);
      params.set("limit", String(limit));
      params.set("offset", String((currentPage - 1) * limit));

      const data = await get<{ users: User[]; total: number }>(
        `/api/users?${params.toString()}`
      );

      setUsers(data.users);
      setTotal(data.total);
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to load users");
    } finally {
      setLoading(false);
    }
  }, [filters, currentPage, limit]);

  // Fetch single user by ID
  const fetchUserById = useCallback(async (id: string) => {
    try {
      const user = await get<User>(`/api/users/${id}`);
      return user;
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to load user");
      return null;
    }
  }, []);

  // Fetch classes for filter dropdown
  const fetchClasses = useCallback(async () => {
    try {
      const data = await get<{ classes: Class[] }>("/api/classes");
      setClasses(data.classes || []);
    } catch (e) {
      console.error("Failed to load classes:", e);
      setClasses([]);
    }
  }, []);

  // Fetch items for inventory management
  const fetchItems = useCallback(async () => {
    try {
      const data = await get<{ items: Item[]; total: number }>("/api/items");
      setItems(data.items || []);
    } catch (e) {
      console.error("Failed to load items:", e);
      setItems([]);
    }
  }, []);

  // Fetch user inventory
  const fetchInventory = useCallback(async (userId: string) => {
    try {
      const data = await get<{ inventory: InventoryEntry[] }>(
        `/api/users/${userId}/inventory`
      );
      setInventoryDraft(data.inventory);
      return data.inventory;
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to load inventory");
      return [];
    }
  }, []);

  // Update user
  const updateUser = useCallback(async (id: string, data: Partial<User>) => {
    try {
      setSaving(true);
      setError(null);

      const result = await put<{ success: boolean; user: User }>(
        `/api/users/${id}`,
        data
      );

      return result.user;
    } catch (e) {
      setError(e instanceof Error ? e.message : "Failed to update user");
      return null;
    } finally {
      setSaving(false);
    }
  }, []);

  // Add item to inventory
  const addInventoryItem = useCallback(
    async (userId: string, itemId: number, quantity: string) => {
      try {
        await post(`/api/users/${userId}/inventory`, { itemId, quantity });
        await fetchInventory(userId);
        return true;
      } catch (e) {
        setError(e instanceof Error ? e.message : "Failed to add item");
        return false;
      }
    },
    [fetchInventory]
  );

  // Remove item from inventory
  const removeInventoryItem = useCallback(
    async (userId: string, itemId: number) => {
      try {
        await del(`/api/users/${userId}/inventory/${itemId}`);
        await fetchInventory(userId);
        return true;
      } catch (e) {
        setError(e instanceof Error ? e.message : "Failed to remove item");
        return false;
      }
    },
    [fetchInventory]
  );

  // Set filters and reset to page 1
  const setFilters = useCallback((newFilters: Partial<UserFilters>) => {
    setFiltersState((prev) => ({ ...prev, ...newFilters }));
    setCurrentPage(1);
  }, []);

  // Debounced search setter
  const setSearchDebounced = useCallback(
    (() => {
      let timeoutId: NodeJS.Timeout;
      return (search: string) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
          setFilters({ search });
        }, 300);
      };
    })(),
    [setFilters]
  );

  // Navigate to page
  const setPage = useCallback((page: number) => {
    setCurrentPage(page);
  }, []);

  // Select user and open detail panel
  const selectUser = useCallback(
    async (user: User) => {
      setSelectedUser(user);

      // Fetch fresh data
      const freshUser = await fetchUserById(user.id);
      if (freshUser) {
        setSelectedUser(freshUser);
        setUserDraft(structuredClone(freshUser));
        await fetchInventory(freshUser.id);
      }
    },
    [fetchUserById, fetchInventory]
  );

  // Close detail panel
  const closeDetail = useCallback(() => {
    setSelectedUser(null);
    setUserDraft(null);
    setInventoryDraft([]);
  }, []);

  // Update draft field
  const updateDraft = useCallback((field: keyof User, value: unknown) => {
    setUserDraft((prev) => {
      if (!prev) return null;
      return { ...prev, [field]: value };
    });
  }, []);

  // Save draft changes
  const saveDraft = useCallback(async () => {
    if (!selectedUser || !userDraft) return false;

    const updated = await updateUser(selectedUser.id, userDraft);
    if (updated) {
      setSelectedUser(updated);
      setUserDraft(structuredClone(updated));

      // Refresh the list to show updated data
      await fetchUsers();
      return true;
    }

    return false;
  }, [selectedUser, userDraft, updateUser, fetchUsers]);

  // Discard draft changes
  const discardDraft = useCallback(() => {
    if (selectedUser) {
      setUserDraft(structuredClone(selectedUser));
    }
  }, [selectedUser]);

  // Check if draft has changes
  const isDirty = useCallback(() => {
    if (!selectedUser || !userDraft) return false;
    return JSON.stringify(selectedUser) !== JSON.stringify(userDraft);
  }, [selectedUser, userDraft]);

  // Initial load
  useEffect(() => {
    fetchUsers();
    fetchClasses();
    fetchItems();
  }, [fetchUsers, fetchClasses, fetchItems]);

  return {
    // User list
    users,
    total,
    currentPage,
    limit,
    setLimit,

    // Filters
    filters,
    setFilters,
    setSearchDebounced,

    // Pagination
    setPage,

    // Detail panel
    selectedUser,
    selectUser,
    closeDetail,

    // Editing
    userDraft,
    updateDraft,
    saveDraft,
    discardDraft,
    isDirty: isDirty(),

    // Inventory
    inventoryDraft,
    addInventoryItem,
    removeInventoryItem,

    // Reference data
    classes,
    items,

    // UI state
    loading,
    saving,
    error,

    // Actions
    refetch: fetchUsers,
  };
}
