import { PrismaClient } from '@prisma/client';

import { getPrismaClient } from '../../../config/database.config';
import { DateRangeDto, RiskFiltersDto } from '../access.dto';

/**
 * EN: Access Analytics Service
 * VI: Service phân tích truy cập
 */
export class AccessAnalyticsService {
  private prisma: PrismaClient;

  constructor() {
    this.prisma = getPrismaClient();
  }

  /**
   * EN: Get usage statistics
   * VI: Lấy thống kê sử dụng
   */
  async getUsageStats(period: DateRangeDto): Promise<any> {
    const startDate = new Date(period.startDate);
    const endDate = new Date(period.endDate);

    const [
      totalUsers,
      activeUsers,
      totalPermissions,
      accessRequests,
      accessReviews,
    ] = await Promise.all([
      this.prisma.user.count({ where: { createdAt: { lte: endDate } } }),
      this.prisma.user.count({
        where: {
          isActive: true,
          lastLoginAt: {
            gte: startDate,
            lte: endDate,
          },
        },
      }),
      this.prisma.permission.count(),
      this.prisma.accessRequest.count({
        where: {
          requestedAt: {
            gte: startDate,
            lte: endDate,
          },
        },
      }),
      this.prisma.accessReview.count({
        where: {
          createdAt: {
            gte: startDate,
            lte: endDate,
          },
        },
      }),
    ]);

    return {
      totalUsers,
      activeUsers,
      totalPermissions,
      accessRequests,
      accessReviews,
      period: {
        startDate,
        endDate,
      },
    };
  }

  /**
   * EN: Get permission distribution
   * VI: Lấy phân bố quyền
   */
  async getPermissionDistribution(): Promise<any> {
    const permissions = await this.prisma.permission.findMany({
      include: {
        roles: {
          select: {
            role: {
              select: {
                id: true,
                name: true,
              },
            },
          },
        },
        users: {
          select: {
            user: {
              select: {
                id: true,
                email: true,
              },
            },
          },
        },
      },
    });

    const distribution = permissions.map((perm) => ({
      permission: {
        id: perm.id,
        resource: perm.resource,
        action: perm.action,
        scope: perm.scope,
      },
      roleCount: perm.roles.length,
      userCount: perm.users.length,
      totalAssignments: perm.roles.length + perm.users.length,
    }));

    return distribution;
  }

  /**
   * EN: Get user access summary
   * VI: Lấy tổng quan truy cập của user
   */
  async getUserAccessSummary(userId: string): Promise<any> {
    const user = await this.prisma.user.findUnique({
      where: { id: userId },
      include: {
        userRoles: {
          include: {
            role: {
              include: {
                permissions: {
                  include: { permission: true },
                },
              },
            },
          },
        },
        userPermissions: {
          include: { permission: true },
        },
        groupMembers: {
          include: {
            group: {
              include: {
                permissions: {
                  include: { permission: true },
                },
              },
            },
          },
        },
      },
    });

    if (!user) {
      throw new Error('User not found');
    }

    // Collect all permissions from roles, direct permissions, and groups
    const permissionsSet = new Set<string>();
    const permissions = [];

    // From roles
    for (const userRole of user.userRoles) {
      for (const rolePerm of userRole.role.permissions) {
        const key = `${rolePerm.permission.resource}:${rolePerm.permission.action}:${rolePerm.permission.scope || 'all'}`;
        if (!permissionsSet.has(key)) {
          permissionsSet.add(key);
          permissions.push({
            source: 'role',
            roleId: userRole.role.id,
            roleName: userRole.role.name,
            permission: rolePerm.permission,
          });
        }
      }
    }

    // From direct permissions
    for (const userPerm of user.userPermissions) {
      const key = `${userPerm.permission.resource}:${userPerm.permission.action}:${userPerm.permission.scope || 'all'}`;
      if (!permissionsSet.has(key)) {
        permissionsSet.add(key);
        permissions.push({
          source: 'direct',
          permission: userPerm.permission,
        });
      }
    }

    // From groups
    for (const groupMember of user.groupMembers) {
      for (const groupPerm of groupMember.group.permissions) {
        const key = `${groupPerm.permission.resource}:${groupPerm.permission.action}:${groupPerm.permission.scope || 'all'}`;
        if (!permissionsSet.has(key)) {
          permissionsSet.add(key);
          permissions.push({
            source: 'group',
            groupId: groupMember.group.id,
            groupName: groupMember.group.name,
            permission: groupPerm.permission,
          });
        }
      }
    }

    return {
      userId: user.id,
      email: user.email,
      roles: user.userRoles.map((ur) => ({
        id: ur.role.id,
        name: ur.role.name,
      })),
      groups: user.groupMembers.map((gm) => ({
        id: gm.group.id,
        name: gm.group.name,
      })),
      permissions,
      totalPermissions: permissions.length,
    };
  }

  /**
   * EN: Get access trends
   * VI: Lấy xu hướng truy cập
   */
  async getAccessTrends(period: DateRangeDto): Promise<any> {
    const startDate = new Date(period.startDate);
    const endDate = new Date(period.endDate);

    // Get daily access request counts
    const requests = await this.prisma.accessRequest.findMany({
      where: {
        requestedAt: {
          gte: startDate,
          lte: endDate,
        },
      },
      select: {
        requestedAt: true,
        status: true,
      },
    });

    // Group by date
    const trends: Record<string, { date: string; requests: number; approved: number; rejected: number }> = {};
    for (const req of requests) {
      const date = req.requestedAt.toISOString().split('T')[0];
      if (!trends[date]) {
        trends[date] = {
          date,
          requests: 0,
          approved: 0,
          rejected: 0,
        };
      }
      trends[date].requests++;
      if (req.status === 'APPROVED') trends[date].approved++;
      if (req.status === 'REJECTED') trends[date].rejected++;
    }

    return Object.values(trends).sort((a, b) => a.date.localeCompare(b.date));
  }

  /**
   * EN: Get risk analysis
   * VI: Lấy phân tích rủi ro
   */
  async getRiskAnalysis(filters: RiskFiltersDto): Promise<any> {
    // This is a placeholder - actual risk analysis would involve more complex logic
    // analyzing user behavior, access patterns, etc.
    const riskScores = await this.prisma.riskScore.findMany({
      where: {
        ...(filters.minScore !== undefined && { score: { gte: filters.minScore } }),
        ...(filters.maxScore !== undefined && { score: { lte: filters.maxScore } }),
        ...(filters.level && { level: filters.level }),
        ...(filters.userId && { userId: filters.userId }),
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            username: true,
          },
        },
      },
      orderBy: {
        score: 'desc',
      },
      take: 100,
    });

    return {
      highRiskUsers: riskScores.filter((rs) => rs.level === 'HIGH' || rs.level === 'CRITICAL'),
      riskDistribution: {
        LOW: riskScores.filter((rs) => rs.level === 'LOW').length,
        MEDIUM: riskScores.filter((rs) => rs.level === 'MEDIUM').length,
        HIGH: riskScores.filter((rs) => rs.level === 'HIGH').length,
        CRITICAL: riskScores.filter((rs) => rs.level === 'CRITICAL').length,
      },
      total: riskScores.length,
    };
  }
}

export const accessAnalyticsService = new AccessAnalyticsService();
