import { Injectable } from '@nestjs/common';
import { BaseService } from '../base/base.service';
import { UserProfile, db, ObjectType, Prisma, VisitType } from '@nice/common';
import EventBus from '@server/utils/event-bus';
@Injectable()
export class VisitService extends BaseService<Prisma.VisitDelegate> {
  constructor() {
    super(db, ObjectType.VISIT);
  }
  async create(args: Prisma.VisitCreateArgs, staff?: UserProfile) {
    const { postId, messageId } = args.data;
    const clientIp = (args.data.meta as any)?.ip;
    const visitorId = args.data.visitorId || staff?.id;
    let result;
    const existingVisit = await db.visit.findFirst({
      where: {
        type: args.data.type,
        OR: [
          {
            AND: [
              { OR: [{ postId }, { messageId }] },
              { visitorId: visitorId || null },
            ],
          },
          {
            AND: [
              { OR: [{ postId }, { messageId }] },
              { visitorId: null },
              { meta: { path: ['ip'], equals: clientIp } },
            ],
          },
        ],
      },
    });
    if (!existingVisit) {
      result = await super.create(args);
    } else if (args.data.type === VisitType.READED) {
      result = await super.update({
        where: { id: existingVisit.id },
        data: {
          ...args.data,
          views: existingVisit.views + 1,
        },
      });
    } else if (args.data.type === VisitType.LIKE) {
      if (!visitorId && existingVisit) {
        const thirtyMinutesAgo = new Date(Date.now() - 30 * 60 * 1000);
        if (existingVisit.updatedAt < thirtyMinutesAgo) {
          // 如果上次更新时间超过30分钟，增加view计数
          result = await super.update({
            where: { id: existingVisit.id },
            data: {
              ...args.data,
              views: existingVisit.views + 1,
            },
          });
        }
      }
    }
    if (postId) {
      if (visitorId) {
        EventBus.emit('updatePostState', {
          id: postId,
        });
      }
      if (args.data.type === VisitType.READED) {
        EventBus.emit('updateVisitCount', {
          objectType: ObjectType.POST,
          id: postId,
          visitType: VisitType.READED,
        });
      }
      if (args.data.type === VisitType.LIKE) {
        EventBus.emit('updateVisitCount', {
          objectType: ObjectType.POST,
          id: postId,
          visitType: VisitType.LIKE,
        });
      }
      if (args.data.type === VisitType.HATE) {
        EventBus.emit('updateVisitCount', {
          objectType: ObjectType.POST,
          id: postId,
          visitType: VisitType.HATE,
        });
      }
    }
    return result;
  }
  async createMany(args: Prisma.VisitCreateManyArgs, staff?: UserProfile) {
    const data = Array.isArray(args.data) ? args.data : [args.data];
    const updatePromises: any[] = [];
    const createData: Prisma.VisitCreateManyInput[] = [];
    await Promise.all(
      data.map(async (item) => {
        if (staff && !item.visitorId) item.visitorId = staff.id;
        const { postId, messageId, visitorId } = item;
        const existingVisit = await db.visit.findFirst({
          where: {
            visitorId,
            OR: [{ postId }, { messageId }],
          },
        });

        if (existingVisit) {
          updatePromises.push(
            super.update({
              where: { id: existingVisit.id },
              data: {
                ...item,
                views: existingVisit.views + 1,
              },
            }),
          );
        } else {
          createData.push(item);
        }
      }),
    );
    // Execute all updates in parallel
    await Promise.all(updatePromises);
    // Create new visits for those not existing
    if (createData.length > 0) {
      return super.createMany({
        ...args,
        data: createData,
      });
    }

    return { count: updatePromises.length }; // Return the number of updates if no new creates
  }
  async deleteMany(args: Prisma.VisitDeleteManyArgs, staff?: UserProfile) {
    // const where = Array.isArray(args.where) ? args.where : [args.where];
    // const updatePromises: any[] = [];
    // const createData: Prisma.VisitCreateManyInput[] = [];
    // super
    // await Promise.all(
    //   data.map(async (item) => {
    //     if (staff && !item.visitorId) item.visitorId = staff.id;
    //     const { postId, messageId, visitorId } = item;
    //     const existingVisit = await db.visit.findFirst({
    //       where: {
    //         visitorId,
    //         OR: [{ postId }, { messageId }],
    //       },
    //     });

    //     if (existingVisit) {
    //       updatePromises.push(
    //         super.update({
    //           where: { id: existingVisit.id },
    //           data: {
    //             ...item,
    //             views: existingVisit.views + 1,
    //           },
    //         }),
    //       );
    //     } else {
    //       createData.push(item);
    //     }
    //   }),
    // );
    // // Execute all updates in parallel
    // await Promise.all(updatePromises);
    // // Create new visits for those not existing
    // if (createData.length > 0) {
    //   return super.createMany({
    //     ...args,
    //     data: createData,
    //   });
    // }
    // return { count: updatePromises.length }; // Return the number of updates if no new creates
    const superDetele = super.deleteMany(args, staff);
    if (args?.where?.postId) {
      if (args.where.type === VisitType.READED) {
        EventBus.emit('updateVisitCount', {
          objectType: ObjectType.POST,
          id: args?.where?.postId as string,
          visitType: VisitType.READED,
        });
      }
      if (args.where.type === VisitType.LIKE) {
        EventBus.emit('updateVisitCount', {
          objectType: ObjectType.POST,
          id: args?.where?.postId as string,
          visitType: VisitType.LIKE,
        });
      }
      if (args.where.type === VisitType.HATE) {
        EventBus.emit('updateVisitCount', {
          objectType: ObjectType.POST,
          id: args?.where?.postId as string,
          visitType: VisitType.HATE,
        });
      }
    }
    return superDetele;
  }
}
