import { Controller, Get, Query, UseGuards } from '@nestjs/common';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import { AuthGuard } from '@nestjs/passport';
import { AdminGuard } from './admin.guard';
import { PrismaService } from '../../prisma/prisma.service';

@ApiTags('管理后台 - 数据分析')
@Controller('admin/analytics')
@UseGuards(AuthGuard('jwt'), AdminGuard)
@ApiBearerAuth()
export class AnalyticsController {
  constructor(private prisma: PrismaService) {}

  @Get('overview')
  async overview(@Query('range') range: string = '7d') {
    const now = new Date();
    let startDate: Date;
    let prevStartDate: Date;
    let prevEndDate: Date;

    switch (range) {
      case 'today':
        startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate());
        prevStartDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
        prevEndDate = startDate;
        break;
      case '30d':
        startDate = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
        prevStartDate = new Date(now.getTime() - 60 * 24 * 60 * 60 * 1000);
        prevEndDate = startDate;
        break;
      case '7d':
      default:
        startDate = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
        prevStartDate = new Date(now.getTime() - 14 * 24 * 60 * 60 * 1000);
        prevEndDate = startDate;
    }

    const [
      totalUsers,
      activeUsers,
      newUsers,
      prevNewUsers,
      totalOrders,
      todayOrders,
      prevTodayOrders,
      totalRevenue,
      todayRevenue,
      totalCourses,
      totalSkills,
    ] = await Promise.all([
      this.prisma.user.count({ where: { deletedAt: null } }),
      this.prisma.user.count({
        where: {
          deletedAt: null,
          updatedAt: { gte: startDate },
        },
      }),
      this.prisma.user.count({
        where: { createdAt: { gte: startDate }, deletedAt: null },
      }),
      this.prisma.user.count({
        where: {
          createdAt: { gte: prevStartDate, lt: prevEndDate },
          deletedAt: null,
        },
      }),
      this.prisma.order.count({ where: { status: 'PAID' } }),
      this.prisma.order.count({
        where: {
          status: 'PAID',
          createdAt: { gte: new Date(now.getFullYear(), now.getMonth(), now.getDate()) },
        },
      }),
      this.prisma.order.count({
        where: {
          status: 'PAID',
          createdAt: {
            gte: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1),
            lt: new Date(now.getFullYear(), now.getMonth(), now.getDate()),
          },
        },
      }),
      this.prisma.order.aggregate({
        _sum: { amount: true },
        where: { status: 'PAID' },
      }),
      this.prisma.order.aggregate({
        _sum: { amount: true },
        where: {
          status: 'PAID',
          createdAt: { gte: new Date(now.getFullYear(), now.getMonth(), now.getDate()) },
        },
      }),
      this.prisma.course.count({ where: { deletedAt: null } }),
      this.prisma.skill.count({ where: { status: 'ACTIVE' } }),
    ]);

    const revenue = totalRevenue._sum.amount || 0;
    const todayRev = todayRevenue._sum.amount || 0;
    const prevRev = todayRev * (prevNewUsers > 0 ? newUsers / prevNewUsers : 1);

    const userGrowth = prevNewUsers > 0 ? ((newUsers - prevNewUsers) / prevNewUsers * 100) : 0;
    const orderGrowth = prevTodayOrders > 0 ? ((todayOrders - prevTodayOrders) / prevTodayOrders * 100) : 0;
    const revGrowth = prevRev > 0 ? ((todayRev - prevRev) / prevRev * 100) : 0;

    return {
      users: {
        total: totalUsers,
        active: activeUsers,
        new: newUsers,
        growth: Math.round(userGrowth * 10) / 10,
      },
      orders: {
        total: totalOrders,
        today: todayOrders,
        growth: Math.round(orderGrowth * 10) / 10,
      },
      revenue: {
        total: revenue,
        today: todayRev,
        growth: Math.round(revGrowth * 10) / 10,
      },
      courses: {
        total: totalCourses,
      },
      skills: {
        total: totalSkills,
      },
    };
  }

  @Get('trend')
  async trend(@Query('type') type: string = 'users', @Query('days') days: number = 30) {
    const now = new Date();
    const startDate = new Date(now.getTime() - days * 24 * 60 * 60 * 1000);

    if (type === 'users') {
      const data = await this.prisma.$queryRaw<{ date: string; count: bigint }[]>`
        SELECT DATE(created_at) as date, COUNT(*) as count 
        FROM users 
        WHERE deleted_at IS NULL AND created_at >= ${startDate}
        GROUP BY DATE(created_at)
        ORDER BY date
      `;
      return data.map(d => ({ date: d.date, count: Number(d.count) }));
    }

    if (type === 'orders') {
      const data = await this.prisma.$queryRaw<{ date: string; count: bigint; revenue: bigint }[]>`
        SELECT DATE(created_at) as date, COUNT(*) as count, COALESCE(SUM(amount), 0) as revenue
        FROM orders 
        WHERE status = 'PAID' AND created_at >= ${startDate}
        GROUP BY DATE(created_at)
        ORDER BY date
      `;
      return data.map(d => ({ date: d.date, count: Number(d.count), revenue: Number(d.revenue) }));
    }

    if (type === 'sessions') {
      const data = await this.prisma.$queryRaw<{ date: string; count: bigint }[]>`
        SELECT DATE(created_at) as date, COUNT(*) as count 
        FROM sandbox_sessions 
        WHERE created_at >= ${startDate}
        GROUP BY DATE(created_at)
        ORDER BY date
      `;
      return data.map(d => ({ date: d.date, count: Number(d.count) }));
    }

    return [];
  }

  @Get('top')
  async top(@Query('type') type: string = 'courses') {
    if (type === 'courses') {
      return this.prisma.course.findMany({
        where: { deletedAt: null, status: 'PUBLISHED' },
        select: { id: true, title: true },
        orderBy: { createdAt: 'desc' },
        take: 10,
      });
    }

    if (type === 'skills') {
      return this.prisma.skill.findMany({
        where: { status: 'ACTIVE' },
        select: { id: true, name: true, category: true },
        orderBy: { sortOrder: 'asc' },
        take: 10,
      });
    }

    return [];
  }
}