import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Logger } from '@nestjs/common';
import { Job } from 'bullmq';
import { PrismaService } from '../../../prisma/prisma.service';
import { TimelineService } from '../services/timeline.service';

export type CrmSchedulerJobName =
  | 'check-overdue-activities'
  | 'check-stale-deals'
  | 'check-unprocessed-leads';

@Processor('crm-scheduler')
export class CrmSchedulerProcessor extends WorkerHost {
  private readonly logger = new Logger(CrmSchedulerProcessor.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly timeline: TimelineService,
  ) {
    super();
  }

  async process(job: Job<any, any, CrmSchedulerJobName>): Promise<void> {
    this.logger.log(`Processing CRM scheduler job: ${job.name}`);

    switch (job.name) {
      case 'check-overdue-activities':
        await this.checkOverdueActivities();
        break;
      case 'check-stale-deals':
        await this.checkStaleDeals();
        break;
      case 'check-unprocessed-leads':
        await this.checkUnprocessedLeads();
        break;
      default:
        this.logger.warn(`Unknown job name: ${String(job.name)}`);
    }
  }

  /** Mark overdue activities and add timeline entries */
  private async checkOverdueActivities(): Promise<void> {
    const overdue = await this.prisma.crmActivity.findMany({
      where: {
        completedAt: null,
        scheduledAt: { lt: new Date() },
        isOverdue: false,
      },
      take: 200,
    });

    if (overdue.length === 0) return;
    this.logger.log(`Found ${overdue.length} overdue activities`);

    for (const activity of overdue) {
      await this.prisma.crmActivity.update({
        where: { id: activity.id },
        data: { isOverdue: true },
      });

      if (activity.dealId) {
        await this.timeline.addEntry(activity.dealId, null, 'SYSTEM', {
          subject: 'Просроченное дело',
          content: `Дело "${activity.subject}" просрочено`,
          metadata: { activityId: activity.id },
        });
      }
    }
  }

  /** Detect deals without activity for 3+ days */
  private async checkStaleDeals(): Promise<void> {
    const staleDays = 3;
    const threshold = new Date();
    threshold.setDate(threshold.getDate() - staleDays);

    const staleDeals = await this.prisma.crmDeal.findMany({
      where: {
        deletedAt: null,
        closedAt: null,
        updatedAt: { lt: threshold },
        activities: {
          none: {
            completedAt: null,
            scheduledAt: { gte: new Date() },
          },
        },
      },
      select: { id: true, title: true, assigneeId: true },
      take: 100,
    });

    if (staleDeals.length === 0) return;
    this.logger.log(`Found ${staleDeals.length} stale deals`);

    for (const deal of staleDeals) {
      await this.timeline.addEntry(deal.id, null, 'SYSTEM', {
        subject: 'Сделка без активности',
        content: `Нет активности по сделке "${deal.title}" более ${staleDays} дней`,
      });
    }
  }

  /** Find leads in first stage for 24+ hours without activity */
  private async checkUnprocessedLeads(): Promise<void> {
    const threshold = new Date();
    threshold.setHours(threshold.getHours() - 24);

    const unprocessed = await this.prisma.crmDeal.findMany({
      where: {
        deletedAt: null,
        closedAt: null,
        createdAt: { lt: threshold },
        stage: { type: 'OPEN' },
        activities: { none: {} },
        timeline: {
          none: {
            type: {
              in: [
                'COMMENT',
                'CALL_INCOMING',
                'CALL_OUTGOING',
                'MESSAGE_TG',
                'MESSAGE_WA',
                'MESSAGE_VK',
                'MESSAGE_EMAIL',
              ],
            },
          },
        },
      },
      select: { id: true, title: true, contactName: true, assigneeId: true },
      take: 100,
    });

    if (unprocessed.length === 0) return;
    this.logger.log(`Found ${unprocessed.length} unprocessed leads`);

    for (const deal of unprocessed) {
      await this.timeline.addEntry(deal.id, null, 'SYSTEM', {
        subject: 'Необработанная заявка',
        content: `Заявка "${deal.contactName || deal.title}" не обработана более 24 часов`,
      });
    }
  }
}
