import { normalizeNullableStringId, normalizeStringId } from './shared';

export interface BackendObjectContextMenuDTO {
  key?: string | null;
  label?: string | null;
  routeKey?: string | null;
  routePath?: string | null;
  id?: string | number | null;
  name?: string | null;
  path?: string | null;
  icon?: string | null;
  sort?: number | null;
  children?: BackendObjectContextMenuDTO[] | null;
}

interface BackendProductContextProductDTO {
  id?: string | number | null;
  code?: string | null;
  directionCode?: string | null;
  name?: string | null;
  managerUserId?: string | number | null;
  statusCode?: string | null;
}

interface BackendProjectContextProjectDTO {
  id?: string | number | null;
  projectCode?: string | null;
  projectName?: string | null;
  projectType?: string | null;
  productId?: string | number | null;
  managerUserId?: string | number | null;
  statusCode?: string | null;
}

interface BackendObjectContextRoleDTO {
  roleId?: string | number | null;
  roleCode?: string | null;
  roleName?: string | null;
  guestFlag?: boolean | null;
}

export interface BackendObjectContextDTO {
  domainKey?: string | null;
  objectType?: string | null;
  objectId?: string | number | null;
  objectName?: string | null;
  objectSummary?: Record<string, unknown> | null;
  menus?: BackendObjectContextMenuDTO[] | null;
  contextScopedMenus?: BackendObjectContextMenuDTO[] | null;
  buttonCodes?: string[] | null;
  currentProduct?: BackendProductContextProductDTO | null;
  currentProject?: BackendProjectContextProjectDTO | null;
  currentRole?: BackendObjectContextRoleDTO | null;
  navs?: BackendObjectContextMenuDTO[] | null;
  buttons?: string[] | null;
  defaultRouteKey?: string | null;
  defaultRoutePath?: string | null;
}

function normalizeString(value: string | number | null | undefined) {
  if (value === null || value === undefined) {
    return '';
  }

  return String(value);
}

function normalizeRoutePath(path: string | null | undefined) {
  const normalizedPath = normalizeString(path).trim();

  if (!normalizedPath) {
    return '';
  }

  if (normalizedPath.startsWith('/')) {
    return normalizedPath;
  }

  return `/${normalizedPath}`;
}

function normalizeCurrentProduct(
  product: BackendProductContextProductDTO
): Record<'id' | 'code' | 'directionCode' | 'name' | 'managerUserId' | 'statusCode', string> {
  return {
    id: normalizeStringId(product.id || ''),
    code: normalizeString(product.code),
    directionCode: normalizeString(product.directionCode),
    name: normalizeString(product.name),
    managerUserId: normalizeNullableStringId(product.managerUserId) ?? '',
    statusCode: normalizeString(product.statusCode)
  };
}

function normalizeCurrentProject(project: BackendProjectContextProjectDTO) {
  return {
    id: normalizeStringId(project.id || ''),
    projectCode: normalizeString(project.projectCode),
    projectName: normalizeString(project.projectName),
    projectType: normalizeString(project.projectType),
    productId: normalizeNullableStringId(project.productId),
    managerUserId: normalizeNullableStringId(project.managerUserId) ?? '',
    statusCode: normalizeString(project.statusCode)
  };
}

function normalizeCurrentRole(role: BackendObjectContextRoleDTO) {
  return {
    roleId: normalizeStringId(role.roleId || ''),
    roleCode: normalizeString(role.roleCode),
    roleName: normalizeString(role.roleName),
    guestFlag: Boolean(role.guestFlag)
  };
}

function normalizeMenu(menu: BackendObjectContextMenuDTO): App.ObjectContext.Menu {
  const routeKey = normalizeString(menu.routeKey);
  const routePath = normalizeRoutePath(menu.routePath || menu.path);
  const key = normalizeString(menu.key || routeKey || routePath || menu.id);

  return {
    key,
    label: normalizeString(menu.label || menu.name),
    routeKey: routeKey || null,
    routePath: routePath || null,
    children: menu.children?.map(child => normalizeMenu(child)) || []
  };
}

function getFirstNonEmptyMenuSource(data: BackendObjectContextDTO) {
  const menuSources = [data.contextScopedMenus, data.menus, data.navs];

  return menuSources.find(source => Array.isArray(source) && source.length > 0) || [];
}

function getFirstRoutableMenu(menus: App.ObjectContext.Menu[]): App.ObjectContext.Menu | null {
  for (const menu of menus) {
    if (menu.routeKey || menu.routePath) {
      return menu;
    }

    const firstChildMenu = menu.children?.length ? getFirstRoutableMenu(menu.children) : null;

    if (firstChildMenu) {
      return firstChildMenu;
    }
  }

  return null;
}

function normalizeObjectSummary(data: BackendObjectContextDTO): App.ObjectContext.Summary | null {
  if (data.objectSummary) {
    return data.objectSummary;
  }

  const summary: App.ObjectContext.Summary = {};

  if (data.currentProduct) {
    summary.currentProduct = normalizeCurrentProduct(data.currentProduct);
  }

  if (data.currentProject) {
    summary.currentProject = normalizeCurrentProject(data.currentProject);
  }

  if (data.currentRole !== undefined) {
    summary.currentRole = data.currentRole ? normalizeCurrentRole(data.currentRole) : null;
  }

  return Object.keys(summary).length ? summary : null;
}

// 待重构：拆 helper 以降低复杂度，暂以 disable 注释临时放行
// eslint-disable-next-line complexity
export function normalizeObjectContext(
  config: App.ObjectContext.DomainConfig,
  objectId: string,
  data: BackendObjectContextDTO
): Api.ObjectContext.ContextInfo {
  const rawMenus = getFirstNonEmptyMenuSource(data);
  const contextScopedMenus = rawMenus.map(menu => normalizeMenu(menu));
  const firstRoutableMenu = getFirstRoutableMenu(contextScopedMenus);
  const currentProduct = data.currentProduct ? normalizeCurrentProduct(data.currentProduct) : null;
  const currentProject = data.currentProject ? normalizeCurrentProject(data.currentProject) : null;

  return {
    domainKey: (data.domainKey || config.domainKey) as App.ObjectContext.DomainKey,
    objectType: (data.objectType || config.objectType) as App.ObjectContext.ObjectType,
    objectId: normalizeString(data.objectId) || currentProduct?.id || currentProject?.id || objectId,
    objectName: normalizeString(data.objectName || currentProduct?.name || currentProject?.projectName),
    objectSummary: normalizeObjectSummary(data),
    contextScopedMenus,
    buttonCodes: data.buttonCodes ?? data.buttons ?? [],
    defaultRouteKey: data.defaultRouteKey || firstRoutableMenu?.routeKey || '',
    defaultRoutePath:
      normalizeRoutePath(data.defaultRoutePath) || firstRoutableMenu?.routePath || config.fallbackDefaultRoutePath
  };
}
