import { Injectable, Logger } from '@nestjs/common';
import { PrismaService } from '../../../prisma/prisma.service';

export interface BotAnalytics {
  subscribers: {
    total: number;
    subscribed: number;
    unsubscribed: number;
    withPhone: number;
    bonusGranted: number;
    mailingConsent: number;
  };
  referrals: {
    totalInvited: number;
    completedReferrals: number;
    averageInvited: number;
  };
  funnel: Array<{
    nodeId: string;
    count: number;
  }>;
  dailyGrowth: Array<{
    date: string;
    count: number;
  }>;
  topSources: Array<{
    source: string;
    count: number;
  }>;
}

@Injectable()
export class AnalyticsService {
  private readonly logger = new Logger(AnalyticsService.name);

  constructor(private readonly prisma: PrismaService) {}

  async getBotAnalytics(botId: string): Promise<BotAnalytics> {
    const [subscribers, referrals, funnel, dailyGrowth, topSources] = await Promise.all([
      this.getSubscriberStats(botId),
      this.getReferralStats(botId),
      this.getFunnelStats(botId),
      this.getDailyGrowth(botId),
      this.getTopSources(botId),
    ]);

    return { subscribers, referrals, funnel, dailyGrowth, topSources };
  }

  private async getSubscriberStats(botId: string) {
    const [total, subscribed, unsubscribed, withPhone, bonusGranted, mailingConsent] =
      await Promise.all([
        this.prisma.tgBotSubscriber.count({ where: { botId } }),
        this.prisma.tgBotSubscriber.count({ where: { botId, isSubscribed: true } }),
        this.prisma.tgBotSubscriber.count({ where: { botId, isSubscribed: false } }),
        this.prisma.tgBotSubscriber.count({ where: { botId, phone: { not: null } } }),
        this.prisma.tgBotSubscriber.count({ where: { botId, bonusGranted: true } }),
        this.prisma.tgBotSubscriber.count({ where: { botId, mailingConsent: true } }),
      ]);
    return { total, subscribed, unsubscribed, withPhone, bonusGranted, mailingConsent };
  }

  private async getReferralStats(botId: string) {
    const result = await this.prisma.tgBotSubscriber.aggregate({
      where: { botId, invitedCount: { gt: 0 } },
      _sum: { invitedCount: true },
      _avg: { invitedCount: true },
      _count: true,
    });

    return {
      totalInvited: result._sum.invitedCount ?? 0,
      completedReferrals: result._count,
      averageInvited: Math.round((result._avg.invitedCount ?? 0) * 10) / 10,
    };
  }

  private async getFunnelStats(botId: string) {
    // Count subscribers at each node (current position in scenario)
    const raw = await this.prisma.tgBotSubscriber.groupBy({
      by: ['currentNodeId'],
      where: { botId, currentNodeId: { not: null } },
      _count: true,
      orderBy: { _count: { currentNodeId: 'desc' } },
    });

    return raw.map((r) => ({
      nodeId: r.currentNodeId ?? 'unknown',
      count: r._count,
    }));
  }

  private async getDailyGrowth(botId: string) {
    // Last 30 days subscriber growth
    const thirtyDaysAgo = new Date();
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);

    const raw = await this.prisma.$queryRaw<Array<{ date: Date; count: bigint }>>`
      SELECT DATE("registeredAt") as date, COUNT(*) as count
      FROM tg_bot_subscribers
      WHERE "botId" = ${botId}
        AND "registeredAt" >= ${thirtyDaysAgo}
      GROUP BY DATE("registeredAt")
      ORDER BY date ASC
    `;

    return raw.map((r) => ({
      date: r.date.toISOString().split('T')[0],
      count: Number(r.count),
    }));
  }

  private async getTopSources(botId: string) {
    const raw = await this.prisma.tgBotSubscriber.groupBy({
      by: ['source'],
      where: { botId, source: { not: null } },
      _count: true,
      orderBy: { _count: { source: 'desc' } },
      take: 10,
    });

    return raw.map((r) => ({
      source: r.source ?? 'unknown',
      count: r._count,
    }));
  }
}
