import 'server-only';
import type { AdminMenu } from '@/lib/domain/admin-menu';
import type { AdminMenuValues } from '@/lib/domain/admin-menu-form';

/**
 * 관리자페이지 메뉴 Repository — 기획 ADM_MNU_001/002_p/003_p.
 *
 * TODO(백엔드): 이 화면의 API가 아직 없다. 아래 mock 저장소를 지우고 다른 Repository처럼
 * backendFetch + getSessionAccessToken으로 교체하면 호출부는 그대로 둘 수 있다.
 *
 * ⚠️ 종전에는 `/api/v1/mngr/menu`(TB_SYS_MENU)를 불렀는데, 그것은 **앱 메뉴**이고
 * 「시스템관리 > 메뉴관리」가 이미 같은 표를 편집한다. 두 화면이 같은 행을 고치게 되어
 * 이 화면에서 삭제하면 앱 메뉴가 사라졌다. 전용 API가 나오기 전까지 mock으로 끊어 둔다.
 *
 * 이슈: 저장소가 모듈 메모리라 서버를 다시 띄우면 수정·삭제가 초기값으로 되돌아간다.
 */

const ALL_USERS = { roleId: 'ROLE_USER', roleName: '모든 사용자' };
const STUDENT = { roleId: 'ROLE_STUDENT', roleName: '수강생' };

let MENUS: AdminMenu[] = [
  {
    id: '14',
    parentId: null,
    name: 'FOX PAY',
    url: '/main',
    description: '메인',
    sortOrder: 1,
    isActive: true,
    isTopActive: true,
    ...ALL_USERS,
  },
  {
    id: '15',
    parentId: '14',
    name: '서비스 소개',
    url: '/intro',
    description: '서비스 소개',
    sortOrder: 1,
    isActive: true,
    isTopActive: false,
    ...ALL_USERS,
  },
  {
    id: '1',
    parentId: null,
    name: '고객센터',
    url: '/cs',
    description: '고객센터',
    sortOrder: 2,
    isActive: true,
    isTopActive: true,
    ...ALL_USERS,
  },
  {
    id: '16',
    parentId: '1',
    name: '이용 문의',
    url: '/cs/inquiry',
    description: '1:1 문의',
    sortOrder: 1,
    isActive: true,
    isTopActive: false,
    ...ALL_USERS,
  },
  {
    id: '4',
    parentId: null,
    name: '내 강의실',
    url: '/class',
    description: '내 강의실',
    sortOrder: 4,
    isActive: true,
    isTopActive: true,
    ...STUDENT,
  },
  {
    id: '5',
    parentId: '4',
    name: '교육 신청 이력',
    url: '/class/history',
    description: '교육 신청 이력',
    sortOrder: 1,
    isActive: true,
    isTopActive: false,
    ...STUDENT,
  },
  {
    id: '9',
    parentId: '4',
    name: '내 정보 수정',
    url: '/class/profile',
    description: '내 정보 수정',
    sortOrder: 6,
    isActive: false,
    isTopActive: false,
    ...STUDENT,
  },
];

/** 기획 ADM_MNU_001 ① — 메뉴 등록순 정렬. */
export async function fetchAdminMenus(): Promise<AdminMenu[]> {
  return MENUS.map((menu) => ({ ...menu }));
}

function roleNameOf(roleId: string): string {
  return (
    MENUS.find((menu) => menu.roleId === roleId)?.roleName ?? roleId
  );
}

export async function createAdminMenu(
  parentId: string,
  values: AdminMenuValues
): Promise<void> {
  if (!MENUS.some((menu) => menu.id === parentId)) {
    throw new Error('상위 메뉴를 찾을 수 없습니다.');
  }

  // 전체에서 가장 큰 번호 다음 — 형제 안에서만 세면 다른 가지와 번호가 겹친다.
  const nextId = MENUS.reduce(
    (max, menu) => Math.max(max, Number(menu.id) || 0),
    0
  ) + 1;

  MENUS = [
    ...MENUS,
    {
      id: String(nextId),
      parentId,
      name: values.name,
      url: values.url,
      description: values.description,
      sortOrder: values.sortOrder,
      roleId: values.roleId,
      roleName: roleNameOf(values.roleId),
      isActive: values.isActive,
      isTopActive: values.isTopActive,
    },
  ];
}

export async function updateAdminMenu(
  menuId: string,
  values: AdminMenuValues
): Promise<void> {
  const index = MENUS.findIndex((menu) => menu.id === menuId);
  if (index < 0) {
    throw new Error('메뉴를 찾을 수 없습니다.');
  }

  MENUS[index] = {
    ...MENUS[index],
    name: values.name,
    url: values.url,
    description: values.description,
    sortOrder: values.sortOrder,
    roleId: values.roleId,
    roleName: roleNameOf(values.roleId),
    isActive: values.isActive,
    isTopActive: values.isTopActive,
  };
}

/** 하위 메뉴까지 함께 지운다 — 부모만 지우면 갈 곳 없는 가지가 남는다. */
export async function deleteAdminMenu(menuId: string): Promise<void> {
  if (!MENUS.some((menu) => menu.id === menuId)) {
    throw new Error('메뉴를 찾을 수 없습니다.');
  }

  const doomed = new Set<string>([menuId]);
  let grew = true;
  while (grew) {
    grew = false;
    for (const menu of MENUS) {
      if (menu.parentId && doomed.has(menu.parentId) && !doomed.has(menu.id)) {
        doomed.add(menu.id);
        grew = true;
      }
    }
  }

  MENUS = MENUS.filter((menu) => !doomed.has(menu.id));
}
