import { AutoWrite, HpsfirIoCContext, Service } from 'hpsfir-ioc';
import { Log, Logger } from 'hpsfir-log';
import { Transaction, HpsfirOrmQuery, HPSFIR_ORM_ORDER_BY_E, AfterOrmConn } from 'hpsfir-orm';
import { TestPo } from '@model/po';
import { PageQueryVo, PageVo, TestAdminVo } from '@model/vo';
import {
  BASE_MENU_TYPE_E,
  BASE_ROUTE_TYPE_E,
  BaseMenuAdminVo,
  BaseMenuService,
  BaseRoleApiPo,
  BaseRouteAdminVo,
  BaseRouteService,
  BaseSnowflakeService,
  BaseApiService,
  BaseOperateService,
} from 'hpsfir-managebase';
import { typeCast } from 'hpsfir-ts-extends';
import { BeforeControllerStart, HpsfirControllerError } from 'hpsfir-controller';
import { TestDao } from '@dao';
import { UserService } from './UserService';
import { ROLE_E } from '@model/enum';
import { BaseOperateAdminVo } from 'hpsfir-managebase/lib/model/vo';

type InitRouteMenuVo = BaseRouteAdminVo & { icon: string };


@Service()
export class InitService {

  @Log(Symbol(InitService.name))
  private logger!: Logger;

  @AutoWrite()
  private baseSnowflakeService!: BaseSnowflakeService;

  @AutoWrite()
  private baseRouteService!: BaseRouteService;

  @AutoWrite()
  private baseMenuService!: BaseMenuService;

  @AutoWrite()
  private userService!: UserService;

  @AutoWrite()
  private baseApiService!: BaseApiService;

  @AutoWrite()
  private baseOperateService!: BaseOperateService;


  // eslint-disable-next-line max-lines-per-function
  @BeforeControllerStart(50)
  @Transaction()
  public async init(ctx?: HpsfirIoCContext) {
    try {
      // 初始化路由
      const initRoute: (InitRouteMenuVo & { children?: InitRouteMenuVo[] })[] = [
        {
          'type': BASE_ROUTE_TYPE_E.ADMIN_PAGE,
          'allowAll': false,
          'title': '测试',
          'path': '/admin/test',
          'componentName': 'test',
          'isNest': false,
          'enable': true,
          'isIndex': true,
          'roleIds': [
            Number(this.userService.roleIdMap?.[ROLE_E.ADMIN]),
            Number(this.userService.roleIdMap?.[ROLE_E.USER]),
          ],
          'icon': 'Monitor',
        },

      ];
      const routes = await this.baseRouteService.listRoutes({}, ctx);
      for (const route of initRoute) {
        if (route.children?.length) {
          for (const child of route.children) {
            let po = routes.find((item) => item.path === child.path);
            if (po) {
              po = {
                ...po,
                ...child,
              };
              await this.baseRouteService.updateRoute(po, ctx);
            } else {
              po = await this.baseRouteService.addRoute(child, ctx);
            }
            child.id = po.id;
          }
        } else {
          let po = routes.find((item) => item.path === route.path);
          if (po) {
            po = {
              ...po,
              ...route,
            };
            await this.baseRouteService.updateRoute(po, ctx);
          } else {
            po = await this.baseRouteService.addRoute(route, ctx);
          }
          route.id = po.id;
        }
      }

      // 初始化菜单
      const initMenu: (BaseMenuAdminVo & { children?: BaseMenuAdminVo[] })[] = initRoute.map((route, inx) => ({
        'url': route.children?.length ? undefined : route.path,
        'type': route.children?.length ? BASE_MENU_TYPE_E.DIR : BASE_MENU_TYPE_E.LINK,
        'title': route.title,
        'sequence': inx + 1,
        'enable': true,
        'roleIds': route.roleIds || [],
        'routeIds': [route.id!],
        'icon': route.icon,
        'children': route.children?.map((child, inxx) => ({
          'url': child.path,
          'type': BASE_MENU_TYPE_E.LINK,
          'title': child.title,
          'sequence': inxx + 1,
          'enable': true,
          'roleIds': child.roleIds || [],
          'routeIds': [child.id!],
          'icon': child.icon,
        })),
      }));
      const menus = await this.baseMenuService.listMenus({}, ctx);
      for (const menu of initMenu) {
        let po = menus.find((item) => (menu.url ? item.url === menu.url : item.title === menu.title));
        if (po) {
          po = {
            ...po,
            ...menu,
          };
          await this.baseMenuService.updateMenu(po, ctx);
        } else {
          po = await this.baseMenuService.addMenu(menu, ctx);
        }
        menu.id = po.id;

        if (menu.children?.length) {
          for (const child of menu.children) {
            let childPo = menus.find((item) => item.url === child.url);
            if (childPo) {
              childPo = {
                ...childPo,
                ...child,
                parentId: menu.id,
              };
              await this.baseMenuService.updateMenu(childPo, ctx);
            } else {
              childPo = await this.baseMenuService.addMenu({
                ...child,
                parentId: menu.id,
              }, ctx);
            }
            child.id = childPo.id;
          }
        }
      }


      // 初始化接口
      const apiRolesMap: any = {
        'upload/file': [ROLE_E.ADMIN, ROLE_E.USER],

      };
      const paths = Object.keys(apiRolesMap);
      const apis = await this.baseApiService.listApis({}, ctx);
      for (const api of apis) {
        for (const path of paths) {
          if (api.path?.includes(path)) {
            const roleKeys = apiRolesMap[path];
            const roleIds = roleKeys.map((key: any) => Number(this.userService.roleIdMap?.[key]));
            const needAddRoleIds = roleIds.filter((id: number) => !api.roleIds?.includes(id));

            // 角色不存在，或者没有包含需要的角色
            // eslint-disable-next-line max-depth
            if (needAddRoleIds.length) {
              await this.baseApiService.updateApi({
                ...api,
                roleIds: [...(api.roleIds || []), ...needAddRoleIds],
              }, ctx);
            }
          }
        }
      }

      // 初始化操作
      const initOperate: BaseOperateAdminVo[] = [
        {
          'key': 'test_edit',
          'name': '编辑(测试)',
          'roleIds': [Number(this.userService.roleIdMap?.[ROLE_E.ADMIN])],
        },
      ];
      const operates = await this.baseOperateService.listOperate({}, ctx);
      for (const operate of initOperate) {
        let po = operates.find((item) => item.key === operate.key);
        if (!po) {
          await this.baseOperateService.addOperate(operate, ctx);
        }
      }
    } catch (error) {
      this.logger.error('初始化系统失败', error);
    }
  }


}
