import { useCallback, useEffect, useRef } from 'react';
import { useGroupManagerStore } from './groupStore';
import { groupManager } from './GroupManager';
import type { GroupResponse, GroupMemberResponse } from '../../types/dto';
import { GROUP_LIST_PAGE_SIZE, GROUP_MEMBER_LIST_PAGE_SIZE } from './sources';

export interface UseGroupsResult {
  groups: GroupResponse[];
  isLoading: boolean;
  refresh: () => Promise<void>;
}

export function useGroups(): UseGroupsResult {
  const groups = useGroupManagerStore(state => state.groupsListEntry?.data ?? []);
  const isLoading = useGroupManagerStore(state => state.isLoadingGroups);
  const hasFetchedRef = useRef(false);

  useEffect(() => {
    if (!hasFetchedRef.current) {
      hasFetchedRef.current = true;
      useGroupManagerStore.getState().setLoadingGroups(true);
      groupManager.getGroups(1, GROUP_LIST_PAGE_SIZE).finally(() => {
        useGroupManagerStore.getState().setLoadingGroups(false);
      });
    }
  }, []);

  const refresh = useCallback(async () => {
    useGroupManagerStore.getState().setLoadingGroups(true);
    try {
      await groupManager.getGroups(1, GROUP_LIST_PAGE_SIZE, true);
    } finally {
      useGroupManagerStore.getState().setLoadingGroups(false);
    }
  }, []);

  return { groups, isLoading, refresh };
}

export interface UseGroupResult {
  group: GroupResponse | null;
  isLoading: boolean;
  refresh: () => Promise<GroupResponse | null>;
}

export function useGroup(groupId: string | undefined | null): UseGroupResult {
  const group = useGroupManagerStore(state =>
    groupId ? (state.groupsMap.get(groupId)?.data ?? null) : null
  );
  const isLoading = useGroupManagerStore(state =>
    groupId ? state.loadingGroupIds.has(groupId) : false
  );
  const lastFetchedRef = useRef<string | null>(null);

  useEffect(() => {
    if (!groupId) return;
    if (lastFetchedRef.current !== groupId) {
      lastFetchedRef.current = groupId;
      useGroupManagerStore.getState().setLoadingGroup(groupId, true);
      groupManager.getGroup(groupId).finally(() => {
        useGroupManagerStore.getState().setLoadingGroup(groupId, false);
      });
    }
  }, [groupId]);

  const refresh = useCallback(async () => {
    if (!groupId) return null;
    useGroupManagerStore.getState().setLoadingGroup(groupId, true);
    try {
      return await groupManager.getGroup(groupId, true);
    } finally {
      useGroupManagerStore.getState().setLoadingGroup(groupId, false);
    }
  }, [groupId]);

  return { group, isLoading, refresh };
}

export interface UseGroupMembersResult {
  members: GroupMemberResponse[];
  isLoading: boolean;
  refresh: () => Promise<void>;
}

export function useGroupMembers(
  groupId: string | undefined | null,
  page = 1,
  pageSize = GROUP_MEMBER_LIST_PAGE_SIZE
): UseGroupMembersResult {
  const membersKey = groupId ? `members:${groupId}:${page}:${pageSize}` : '';
  const members = useGroupManagerStore(state =>
    membersKey ? (state.membersMap.get(membersKey)?.data ?? []) : []
  );
  const isLoading = useGroupManagerStore(state =>
    membersKey ? state.loadingMemberKeys.has(membersKey) : false
  );
  const lastFetchedRef = useRef<string | null>(null);

  useEffect(() => {
    if (!groupId) return;
    const key = `${groupId}:${page}:${pageSize}`;
    if (lastFetchedRef.current !== key) {
      lastFetchedRef.current = key;
      useGroupManagerStore.getState().setLoadingMembers(groupId, true, page, pageSize);
      groupManager.getMembers(groupId, page, pageSize).finally(() => {
        useGroupManagerStore.getState().setLoadingMembers(groupId, false, page, pageSize);
      });
    }
  }, [groupId, page, pageSize]);

  const refresh = useCallback(async () => {
    if (!groupId) return;
    useGroupManagerStore.getState().setLoadingMembers(groupId, true, page, pageSize);
    try {
      await groupManager.getMembers(groupId, page, pageSize, true);
    } finally {
      useGroupManagerStore.getState().setLoadingMembers(groupId, false, page, pageSize);
    }
  }, [groupId, page, pageSize]);

  return { members, isLoading, refresh };
}