import { Injectable } from '@nestjs/common';
import {
  TermMethodSchema,
  db,
  Staff,
  Term,
  Prisma,
  TermDto,
  TreeDataNode,
  UserProfile,
  getUniqueItems,
  RolePerms,
  TaxonomySlug,
  ObjectType,
  TermAncestry,
} from '@nice/common';
import { z } from 'zod';
import { BaseTreeService } from '../base/base.tree.service';
import EventBus, { CrudOperation } from '@server/utils/event-bus';
import { formatToTermTreeData, mapToTermSimpleTree } from './utils';

@Injectable()
export class TermService extends BaseTreeService<Prisma.TermDelegate> {
  constructor() {
    super(db, ObjectType.TERM, 'termAncestry', true);
  }

  async create(args: Prisma.TermCreateArgs, params?: { staff?: UserProfile }) {
    args.data.createdBy = params?.staff?.id;
    const result = await super.create(args);
    EventBus.emit('dataChanged', {
      type: this.objectType,
      operation: CrudOperation.CREATED,
      data: result,
    });
    return result;
  }
  async update(args: Prisma.TermUpdateArgs) {
    const result = await super.update(args);
    EventBus.emit('dataChanged', {
      type: this.objectType,
      operation: CrudOperation.UPDATED,
      data: result,
    });
    return result;
  }

  /**
   * 删除现有单位并清理DeptAncestry关系。
   * @param data - 用于删除现有单位的数据。
   * @returns 删除的单位对象。
   */
  async softDeleteByIds(ids: string[]) {
    const descendantIds = await this.getDescendantIds(ids, true);
    const result = await super.softDeleteByIds(descendantIds);
    EventBus.emit('dataChanged', {
      type: this.objectType,
      operation: CrudOperation.DELETED,
      data: result,
    });
    return result;
  }

  // async query(data: z.infer<typeof TermMethodSchema.findManyWithCursor>) {
  //   const { limit = 10, initialIds, taxonomyId, taxonomySlug } = data;
  //   // Fetch additional objects excluding initialIds
  //   const ids =
  //     typeof initialIds === 'string' ? [initialIds] : initialIds || [];
  //   const initialTerms = await db.term.findMany({
  //     where: {
  //       id: {
  //         in: ids,
  //       },
  //     },
  //     include: {
  //       domain: true,
  //       children: true,
  //     },
  //   });
  //   const terms = await db.term.findMany({
  //     where: {
  //       taxonomyId,
  //       taxonomy: taxonomySlug && { slug: taxonomySlug },
  //       deletedAt: null,
  //     },
  //     take: limit !== -1 ? limit! : undefined,
  //     include: {
  //       domain: true,
  //       taxonomy: true,
  //     },
  //     orderBy: [{ order: 'asc' }, { createdAt: 'desc' }],
  //   });

  //   const results = getUniqueItems(
  //     [...initialTerms, ...terms].filter(Boolean),
  //     'id',
  //   );
  //   return results;
  // }
  // /**

  async upsertTags(staff: UserProfile, tags: string[]) {
    const tagTax = await db.taxonomy.findFirst({
      where: {
        slug: TaxonomySlug.TAG,
      },
    });
    // 批量查找所有存在的标签
    const existingTerms = await db.term.findMany({
      where: {
        name: {
          in: tags,
        },
        taxonomyId: tagTax.id,
      },
    });

    // 找出不存在的标签
    const existingTagNames = new Set(existingTerms.map((term) => term.name));
    const newTags = tags.filter((tag) => !existingTagNames.has(tag));
    // 批量创建不存在的标签
    const newTerms = await Promise.all(
      newTags.map((tag) =>
        this.create({
          data: {
            name: tag,
            taxonomyId: tagTax.id,
            domainId: staff.domainId,
          },
        }),
      ),
    );

    // 合并现有标签和新创建的标签
    return [...existingTerms, ...newTerms];
  }

  // /**
  //  * 查找多个术语并生成TermDto对象。
  //  *
  //  * @param staff 当前操作的工作人员
  //  * @param ids 术语ID
  //  * @returns 包含详细信息的术语对象
  //  */
  // async findByIds(ids: string[], staff?: UserProfile) {
  //   const terms = await db.term.findMany({
  //     where: {
  //       id: {
  //         in: ids,
  //       },
  //     },
  //     include: {
  //       domain: true,
  //       children: true,
  //     },
  //   });
  //   return await Promise.all(
  //     terms.map(async (term) => {
  //       return await this.transformDto(term, staff);
  //     }),
  //   );
  // }
  // /**
  //  * 获取指定条件下的术语子节点。
  //  *
  //  * @param staff 当前操作的工作人员
  //  * @param data 查询条件
  //  * @returns 子节点术语列表
  //  */
  // async getChildren(
  //   staff: UserProfile,
  //   data: z.infer<typeof TermMethodSchema.getChildren>,
  // ) {
  //   const { parentId, domainId, taxonomyId, cursor, limit = 10 } = data;
  //   let queryCondition: Prisma.TermWhereInput = {
  //     taxonomyId,
  //     parentId: parentId,
  //     OR: [{ domainId: null }],
  //     deletedAt: null,
  //   };
  //   if (
  //     staff?.permissions?.includes(RolePerms.MANAGE_ANY_TERM) ||
  //     staff?.permissions?.includes(RolePerms.READ_ANY_TERM)
  //   ) {
  //     queryCondition.OR = undefined;
  //   } else {
  //     queryCondition.OR = queryCondition.OR.concat([
  //       { domainId: staff?.domainId },
  //       { domainId: null },
  //     ]);
  //   }
  //   const terms = await db.term.findMany({
  //     where: queryCondition,
  //     include: {
  //       children: {
  //         where: {
  //           deletedAt: null,
  //         },
  //       },
  //     },
  //     take: limit + 1,
  //     cursor: cursor
  //       ? { createdAt: cursor.split('_')[0], id: cursor.split('_')[1] }
  //       : undefined,
  //   });
  //   let nextCursor: typeof cursor | undefined = undefined;
  //   if (terms.length > limit) {
  //     const nextItem = terms.pop();
  //     nextCursor = `${nextItem.createdAt.toISOString()}_${nextItem!.id}`;
  //   }
  //   const termDtos = await Promise.all(
  //     terms.map((item) => this.transformDto(item, staff)),
  //   );
  //   return {
  //     items: termDtos,
  //     nextCursor,
  //   };
  // }

  async getTreeData(data: z.infer<typeof TermMethodSchema.getTreeData>) {
    const { taxonomyId, taxonomySlug, domainId } = data;
    let terms = [];
    if (taxonomyId) {
      terms = await db.term.findMany({
        where: { taxonomyId, domainId, deletedAt: null },
        include: { children: true },
        orderBy: [{ order: 'asc' }],
      });
    } else if (taxonomySlug) {
      terms = await db.term.findMany({
        where: {
          taxonomy: {
            slug: taxonomySlug,
          },
          deletedAt: null,
          domainId,
        },
        include: { children: true },
        orderBy: [{ order: 'asc' }],
      });
    }
    // Map to store terms by id for quick lookup
    const termMap = new Map<string, any>();
    terms.forEach((term) =>
      termMap.set(term.id, {
        ...term,
        children: [],
        key: term.id,
        value: term.id,
        title: term.name,
        isLeaf: true, // Initialize as true, will update later if it has children
      }),
    );
    // Root nodes collection
    const roots = [];
    // Build the tree structure iteratively
    terms.forEach((term) => {
      if (term.parentId) {
        const parent = termMap.get(term.parentId);
        if (parent) {
          parent.children.push(termMap.get(term.id));
          parent.isLeaf = false; // Update parent's isLeaf field
        }
      } else {
        roots.push(termMap.get(term.id));
      }
    });
    return roots as TreeDataNode[];
  }

  async getChildSimpleTree(
    data: z.infer<typeof TermMethodSchema.getSimpleTree>,
    staff?: UserProfile,
  ) {
    const domainId = staff?.domainId || null;
    const hasAnyPerms =
      staff?.permissions?.includes(RolePerms.MANAGE_ANY_TERM) ||
      staff?.permissions?.includes(RolePerms.READ_ANY_TERM);
    const { termIds, parentId, taxonomyId } = data;
    // 提取非空 deptIds
    const validTermIds = termIds?.filter((id) => id !== null) ?? [];
    const hasNullTermId = termIds?.includes(null) ?? false;

    const [childrenData, selfData] = await Promise.all([
      db.termAncestry.findMany({
        where: {
          ...(termIds && {
            OR: [
              ...(validTermIds.length
                ? [{ ancestorId: { in: validTermIds } }]
                : []),
              ...(hasNullTermId ? [{ ancestorId: null }] : []),
            ],
          }),
          descendant: {
            taxonomyId: taxonomyId,
            // 动态权限控制条件
            ...(hasAnyPerms
              ? {} // 当有全局权限时，不添加任何额外条件
              : {
                  // 当无全局权限时，添加域ID过滤
                  OR: [
                    { domainId: null }, // 通用记录
                    { domainId: domainId }, // 特定域记录
                  ],
                }),
          },
          ancestorId: parentId,
          relDepth: 1,
        },
        include: {
          descendant: { include: { children: true } },
        },
        orderBy: { descendant: { order: 'asc' } },
      }),
      termIds
        ? db.term.findMany({
            where: {
              ...(termIds && {
                OR: [
                  ...(validTermIds.length
                    ? [{ id: { in: validTermIds } }]
                    : []),
                ],
              }),
              taxonomyId: taxonomyId,
              // 动态权限控制条件
              ...(hasAnyPerms
                ? {} // 当有全局权限时，不添加任何额外条件
                : {
                    // 当无全局权限时，添加域ID过滤
                    OR: [
                      { domainId: null }, // 通用记录
                      { domainId: domainId }, // 特定域记录
                    ],
                  }),
            },
            include: { children: true },
            orderBy: { order: 'asc' },
          })
        : [],
    ]);
    const children = childrenData
      .map(({ descendant }) => descendant)
      .filter(Boolean)
      .map(formatToTermTreeData);
    const selfItems = selfData.map(formatToTermTreeData);
    return getUniqueItems([...children, ...selfItems], 'id');
  }

  async getParentSimpleTree(
    staff: UserProfile,
    data: z.infer<typeof TermMethodSchema.getSimpleTree>,
  ) {
    // const { domainId = null, permissions } = staff;
    const permissions = staff?.permissions || [];
    const domainId = staff?.domainId || null;
    const hasAnyPerms =
      permissions.includes(RolePerms.READ_ANY_TERM) ||
      permissions.includes(RolePerms.MANAGE_ANY_TERM);
    // 解构输入参数
    const { termIds, taxonomyId } = data;

    // 并行查询父级部门ancestry和自身部门数据
    // 使用Promise.all提高查询效率,减少等待时间
    const [parentData, selfData] = await Promise.all([
      // 查询指定部门的所有祖先节点,包含子节点和父节点信息
      db.termAncestry.findMany({
        where: {
          descendantId: { in: termIds }, // 查询条件:descendant在给定的部门ID列表中
          ancestor: {
            taxonomyId: taxonomyId,
            ...(hasAnyPerms
              ? {} // 当有全局权限时，不添加任何额外条件
              : {
                  // 当无全局权限时，添加域ID过滤
                  OR: [
                    { domainId: null }, // 通用记录
                    { domainId: domainId }, // 特定域记录
                  ],
                }),
          },
        },
        include: {
          ancestor: {
            include: {
              children: true, // 包含子节点信息
              parent: true, // 包含父节点信息
            },
          },
        },
        orderBy: { ancestor: { order: 'asc' } }, // 按祖先节点顺序升序排序
      }),

      // 查询自身部门数据
      db.term.findMany({
        where: {
          id: { in: termIds },
          taxonomyId: taxonomyId,
          ...(hasAnyPerms
            ? {} // 当有全局权限时，不添加任何额外条件
            : {
                // 当无全局权限时，添加域ID过滤
                OR: [
                  { domainId: null }, // 通用记录
                  { domainId: domainId }, // 特定域记录
                ],
              }),
        },
        include: { children: true }, // 包含子节点信息
        orderBy: { order: 'asc' }, // 按顺序升序排序
      }),
    ]);

    // 处理父级节点:过滤并映射为简单树结构
    const parents = parentData
      .map(({ ancestor }) => ancestor) // 提取祖先节点
      .filter((ancestor) => ancestor) // 过滤有效且超出根节点层级的节点
      .map(mapToTermSimpleTree); // 映射为简单树结构

    // 处理自身节点:映射为简单树结构
    const selfItems = selfData.map(mapToTermSimpleTree);

    // 合并并去重父级和自身节点,返回唯一项
    return getUniqueItems([...parents, ...selfItems], 'id');
  }
}
