'use client';

import { createContext, useContext, useEffect, useState, useCallback } from 'react';
import { usePathname } from 'next/navigation';
import { getRolePermissionMatrix, getPermissionMenuUrlMap } from '@/lib/permissions/actions';
import { buildMenuIdToUrlMap, convertMatrixToPermissionMap, findMatchingUrl, mergePermissionMaps } from '@/lib/permissions/utils';
import { ALL_DENIED_PERMS } from '@/lib/permissions/types';
import type { PermissionMap, PermissionAction } from '@/lib/permissions/types';
import { AccessDenied } from '@/components/common/AccessDenied';
import { stripLocalePrefix } from '@/lib/utils/locale';

interface PermissionContextType {
  permissionMap: PermissionMap | null;
  isLoading: boolean;
  /** URL 지정 권한 체크 (특수 케이스용) */
  can: (url: string, action: PermissionAction) => boolean;
  /** 권한 데이터 다시 로드 (설정 변경 후 호출) */
  reloadPermissions: () => void;
}

const PermissionContext = createContext<PermissionContextType>({
  permissionMap: null,
  isLoading: true,
  can: () => true,
  reloadPermissions: () => {},
});

export function PermissionProvider({ children }: { children: React.ReactNode }) {
  const [permissionMap, setPermissionMap] = useState<PermissionMap | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  const loadPermissions = useCallback(async () => {
    const userData = getUserData();
    if (!userData || userData.roleIds.length === 0) {
      setIsLoading(false);
      return;
    }

    const { roleIds, menuIdToUrl } = userData;
    setIsLoading(true);
    try {
      // 사이드바 메뉴에 없는 권한 메뉴의 URL 매핑 보완
      // (기준정보 관리, 공정관리 등 사이드바 미등록 메뉴 대응)
      const [permMenuUrlMap, ...results] = await Promise.all([
        getPermissionMenuUrlMap(),
        ...roleIds.map(id => getRolePermissionMatrix(id)),
      ]);

      // 권한 메뉴 URL을 베이스로, 사이드바 메뉴 URL로 덮어쓰기 (사이드바 우선)
      const mergedMenuIdToUrl = { ...permMenuUrlMap, ...menuIdToUrl };

      const maps = results
        .filter(r => r.success && r.data?.permissions)
        .map(r => convertMatrixToPermissionMap(r.data.permissions, mergedMenuIdToUrl));

      if (maps.length > 0) {
        const merged = mergePermissionMaps(maps);

        // 권한 메뉴에 등록되어 있지만 매트릭스 응답에 없는 메뉴 처리
        // (모든 권한 OFF → API가 해당 menuId를 생략 → "all denied"로 보완)
        for (const [, url] of Object.entries(permMenuUrlMap)) {
          if (url && !merged[url]) {
            merged[url] = { ...ALL_DENIED_PERMS };
          }
        }

        setPermissionMap(merged);
      } else {
        setPermissionMap(null);
      }
    } catch (error) {
      console.error('[Permission] 권한 로드 실패:', error);
      setPermissionMap(null);
    }
    setIsLoading(false);
  }, []);

  // 마운트 시 1회 로드
  useEffect(() => {
    loadPermissions();
  }, [loadPermissions]);

  const can = useCallback((url: string, action: PermissionAction): boolean => {
    if (!permissionMap) return true;
    const matchedUrl = findMatchingUrl(url, permissionMap);
    if (!matchedUrl) return true;
    const perms = permissionMap[matchedUrl];
    return perms?.[action] ?? true;
  }, [permissionMap]);

  return (
    <PermissionContext.Provider value={{ permissionMap, isLoading, can, reloadPermissions: loadPermissions }}>
      {children}
    </PermissionContext.Provider>
  );
}

/**
 * 자기 잠금(self-lockout) 방지: 권한 설정 페이지는 항상 접근 허용
 */
const BYPASS_PATHS = ['/settings/permissions'];

function isGateBypassed(pathname: string): boolean {
  const pathWithoutLocale = stripLocalePrefix(pathname);
  return BYPASS_PATHS.some(bp => pathWithoutLocale.startsWith(bp));
}

/**
 * PermissionGate: 레이아웃에 배치하여 모든 페이지 자동 보호
 */
export function PermissionGate({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();
  const { permissionMap, isLoading } = useContext(PermissionContext);

  if (isLoading) return null;
  if (!permissionMap) {
    return <>{children}</>;
  }

  if (isGateBypassed(pathname)) return <>{children}</>;

  const matchedUrl = findMatchingUrl(pathname, permissionMap);

  if (!matchedUrl) {
    return <>{children}</>;
  }

  const perms = permissionMap[matchedUrl];
  const canView = perms?.view ?? true;

  if (!canView) {
    return <AccessDenied />;
  }

  return <>{children}</>;
}

/** localStorage 'user' 키에서 역할 ID 배열 + menuId→URL 매핑 추출 */
function getUserData(): { roleIds: number[]; menuIdToUrl: Record<string, string> } | null {
  if (typeof window === 'undefined') return null;
  try {
    const raw = localStorage.getItem('user');
    if (!raw) return null;

    const parsed = JSON.parse(raw);

    const roleIds = Array.isArray(parsed.roles)
      ? parsed.roles.map((r: { id: number }) => r.id).filter(Boolean)
      : [];

    const menuIdToUrl = Array.isArray(parsed.menu)
      ? buildMenuIdToUrlMap(parsed.menu)
      : {};

    return { roleIds, menuIdToUrl };
  } catch {
    return null;
  }
}

export const usePermissionContext = () => useContext(PermissionContext);
