'use client';

import { useMemo } from 'react';
import { useSession } from 'next-auth/react';
import type { NavGroup, NavItem } from '@/types';
import { getBusinessRole, hasBusinessRoleAccess, isSuperAdmin } from '@/lib/auth/roles';

function canAccessItem(
  item: NavItem,
  accessContext: {
    hasOrg: boolean;
    role: string | null;
    businessRole: 'IT' | 'HRD' | 'EMPLOYEE' | null;
    systemRole: string | null;
    permissions: string[];
  }
) {
  if (!item.access) {
    return true;
  }

  if (item.access.systemRole && accessContext.systemRole !== item.access.systemRole) {
    return false;
  }

  if (item.access.requireOrg && !accessContext.hasOrg && !isSuperAdmin(accessContext.systemRole)) {
    return false;
  }

  if (item.access.permission) {
    if (!accessContext.hasOrg && !isSuperAdmin(accessContext.systemRole)) {
      return false;
    }

    if (
      !isSuperAdmin(accessContext.systemRole) &&
      !accessContext.permissions.includes(item.access.permission)
    ) {
      return false;
    }
  }

  if (item.access.role) {
    if (!accessContext.hasOrg && !isSuperAdmin(accessContext.systemRole)) {
      return false;
    }

    if (!isSuperAdmin(accessContext.systemRole) && accessContext.role !== item.access.role) {
      return false;
    }
  }

  if (item.access.businessRole) {
    if (!accessContext.hasOrg && !isSuperAdmin(accessContext.systemRole)) {
      return false;
    }

    if (
      !hasBusinessRoleAccess(item.access.businessRole, {
        businessRole: accessContext.businessRole,
        systemRole: accessContext.systemRole,
        role: accessContext.role
      })
    ) {
      return false;
    }
  }

  if (item.access.businessRoles?.length) {
    if (!accessContext.hasOrg && !isSuperAdmin(accessContext.systemRole)) {
      return false;
    }

    if (
      !item.access.businessRoles.some((businessRole) =>
        hasBusinessRoleAccess(businessRole, {
          businessRole: accessContext.businessRole,
          systemRole: accessContext.systemRole,
          role: accessContext.role
        })
      )
    ) {
      return false;
    }
  }

  if (item.access.plan || item.access.feature) {
    console.warn(
      `Plan/feature checks for navigation items require server-side verification. ` +
        `Item "${item.title}" will be shown, but page-level protection should be implemented.`
    );
  }

  return true;
}

export function useFilteredNavItems(items: NavItem[]) {
  const { data: session } = useSession();

  const accessContext = useMemo(
    () => ({
      hasOrg: !!session?.user?.activeOrganizationId,
      role: session?.user?.role ?? null,
      businessRole: getBusinessRole({
        businessRole: session?.user?.businessRole ?? null,
        systemRole: session?.user?.systemRole ?? null,
        membershipRole: session?.user?.membershipRole ?? null,
        role: session?.user?.role ?? null
      }),
      systemRole: session?.user?.systemRole ?? null,
      permissions: session?.user?.permissions ?? []
    }),
    [
      session?.user?.activeOrganizationId,
      session?.user?.businessRole,
      session?.user?.membershipRole,
      session?.user?.permissions,
      session?.user?.role,
      session?.user?.systemRole
    ]
  );

  const filteredItems = useMemo(() => {
    return items
      .filter((item) => canAccessItem(item, accessContext))
      .map((item) => {
        const hadChildren = !!item.items?.length;

        if (!hadChildren) {
          return item;
        }

        return {
          ...item,
          items: item.items?.filter((childItem) => canAccessItem(childItem, accessContext)) ?? []
        };
      })
      .filter((item) => {
        const sourceItem = items.find((candidate) => candidate.title === item.title);
        const sourceHadChildren = !!sourceItem?.items?.length;
        const visibleChildrenCount = item.items?.length ?? 0;

        if (!sourceHadChildren) {
          return true;
        }

        return visibleChildrenCount > 0;
      });
  }, [accessContext, items]);

  return filteredItems;
}

export function useFilteredNavGroups(groups: NavGroup[]) {
  const allItems = useMemo(() => groups.flatMap((group) => group.items), [groups]);
  const filteredItems = useFilteredNavItems(allItems);

  return useMemo(() => {
    const filteredSet = new Set(filteredItems.map((item) => item.title));

    return groups
      .map((group) => ({
        ...group,
        items: filteredItems.filter((item) =>
          group.items.some(
            (groupItem) => groupItem.title === item.title && filteredSet.has(groupItem.title)
          )
        )
      }))
      .filter((group) => group.items.length > 0);
  }, [filteredItems, groups]);
}
