import { logger } from '@goodgo/logger';
import { PrismaClient, ComplianceType, ReportStatus } from '@prisma/client';
import { Request } from 'express';

import { getPrismaClient } from '../../../config/database.config';
import { auditService } from '../../../core/events/audit.service';
import { NotFoundError, BadRequestError } from '../../../errors/http-error';
import { ReportFiltersDto } from '../governance.dto';

/**
 * EN: Compliance Reporting Service
 * VI: Service báo cáo tuân thủ
 */
export class ComplianceService {
  private prisma: PrismaClient;

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

  /**
   * EN: Generate compliance report
   * VI: Tạo báo cáo tuân thủ
   */
  async generateReport(
    type: ComplianceType,
    periodStart: Date,
    periodEnd: Date,
    generatedBy: string,
    req?: Request
  ): Promise<any> {
    if (periodEnd <= periodStart) {
      throw new BadRequestError('End date must be after start date / Ngày kết thúc phải sau ngày bắt đầu');
    }

    let reportData: any = {};

    // Generate report data based on type
    switch (type) {
      case 'GDPR':
        reportData = await this.generateGDPRReport(periodStart, periodEnd);
        break;
      case 'SOC2':
        reportData = await this.generateSOC2Report(periodStart, periodEnd);
        break;
      case 'ISO27001':
        reportData = await this.generateISO27001Report(periodStart, periodEnd);
        break;
      default:
        reportData = await this.generateCustomReport(periodStart, periodEnd);
    }

    const report = await this.prisma.complianceReport.create({
      data: {
        type,
        name: `${type} Report - ${periodStart.toISOString().split('T')[0]} to ${periodEnd.toISOString().split('T')[0]}`,
        periodStart,
        periodEnd,
        status: ReportStatus.GENERATED,
        data: reportData,
        generatedAt: new Date(),
        generatedBy,
      },
    });

    if (req) {
      await auditService.logFromRequest(req, 'COMPLIANCE_REPORT_GENERATED', {
        reportId: report.id,
        type,
        success: true,
      });
    }

    logger.info('Compliance report generated', { reportId: report.id, type });

    return report;
  }

  /**
   * EN: Generate GDPR report
   * VI: Tạo báo cáo GDPR
   */
  private async generateGDPRReport(periodStart: Date, periodEnd: Date): Promise<any> {
    const [
      totalUsers,
      usersWithData,
      dataAccessRequests,
      dataDeletionRequests,
      consentRecords,
    ] = await Promise.all([
      this.prisma.user.count({ where: { createdAt: { lte: periodEnd } } }),
      this.prisma.user.count({
        where: {
          profile: { isNot: null },
        },
      }),
      this.prisma.accessRequest.count({
        where: {
          resource: 'user_data',
          requestedAt: { gte: periodStart, lte: periodEnd },
        },
      }),
      this.prisma.user.count({
        where: {
          isActive: false,
          updatedAt: { gte: periodStart, lte: periodEnd },
        },
      }),
      0, // Placeholder for consent records
    ]);

    return {
      summary: {
        totalUsers,
        usersWithData,
        dataAccessRequests,
        dataDeletionRequests,
        consentRecords,
      },
      period: { start: periodStart, end: periodEnd },
      generatedAt: new Date(),
    };
  }

  /**
   * EN: Generate SOC2 report
   * VI: Tạo báo cáo SOC2
   */
  private async generateSOC2Report(periodStart: Date, periodEnd: Date): Promise<any> {
    const [
      totalAccessRequests,
      approvedRequests,
      rejectedRequests,
      accessReviews,
      securityIncidents,
    ] = await Promise.all([
      this.prisma.accessRequest.count({
        where: {
          requestedAt: { gte: periodStart, lte: periodEnd },
        },
      }),
      this.prisma.accessRequest.count({
        where: {
          status: 'APPROVED',
          requestedAt: { gte: periodStart, lte: periodEnd },
        },
      }),
      this.prisma.accessRequest.count({
        where: {
          status: 'REJECTED',
          requestedAt: { gte: periodStart, lte: periodEnd },
        },
      }),
      this.prisma.accessReview.count({
        where: {
          createdAt: { gte: periodStart, lte: periodEnd },
        },
      }),
      this.prisma.authEvent.count({
        where: {
          eventType: { in: ['SECURITY_INCIDENT', 'UNAUTHORIZED_ACCESS'] },
          success: false,
          timestamp: { gte: periodStart, lte: periodEnd },
        },
      }),
    ]);

    return {
      accessControl: {
        totalRequests: totalAccessRequests,
        approved: approvedRequests,
        rejected: rejectedRequests,
        approvalRate: totalAccessRequests > 0 ? (approvedRequests / totalAccessRequests) * 100 : 0,
      },
      accessReviews,
      securityIncidents,
      period: { start: periodStart, end: periodEnd },
      generatedAt: new Date(),
    };
  }

  /**
   * EN: Generate ISO27001 report
   * VI: Tạo báo cáo ISO27001
   */
  private async generateISO27001Report(periodStart: Date, periodEnd: Date): Promise<any> {
    // Similar structure to SOC2 but with ISO27001 specific metrics
    return this.generateSOC2Report(periodStart, periodEnd);
  }

  /**
   * EN: Generate custom report
   * VI: Tạo báo cáo tùy chỉnh
   */
  private async generateCustomReport(periodStart: Date, periodEnd: Date): Promise<any> {
    return {
      period: { start: periodStart, end: periodEnd },
      generatedAt: new Date(),
      note: 'Custom report - data structure varies',
    };
  }

  /**
   * EN: Get report by ID
   * VI: Lấy báo cáo theo ID
   */
  async getReport(id: string): Promise<any> {
    const report = await this.prisma.complianceReport.findUnique({
      where: { id },
    });

    if (!report) {
      throw new NotFoundError('Compliance Report');
    }

    return report;
  }

  /**
   * EN: Get reports with filters
   * VI: Lấy các báo cáo với filters
   */
  async getReports(filters: ReportFiltersDto): Promise<{ reports: any[]; total: number }> {
    const where: any = {};

    if (filters.type) {
      where.type = filters.type;
    }

    if (filters.status) {
      where.status = filters.status;
    }

    if (filters.startDate || filters.endDate) {
      where.OR = [];
      if (filters.startDate) {
        where.OR.push({ periodEnd: { gte: new Date(filters.startDate) } });
      }
      if (filters.endDate) {
        where.OR.push({ periodStart: { lte: new Date(filters.endDate) } });
      }
    }

    const [reports, total] = await Promise.all([
      this.prisma.complianceReport.findMany({
        where,
        skip: filters.skip,
        take: filters.take,
        orderBy: { createdAt: 'desc' },
      }),
      this.prisma.complianceReport.count({ where }),
    ]);

    return { reports, total };
  }

  /**
   * EN: Publish report
   * VI: Xuất bản báo cáo
   */
  async publishReport(id: string, req?: Request): Promise<any> {
    const report = await this.prisma.complianceReport.findUnique({ where: { id } });
    if (!report) {
      throw new NotFoundError('Compliance Report');
    }

    const updated = await this.prisma.complianceReport.update({
      where: { id },
      data: { status: ReportStatus.PUBLISHED },
    });

    if (req) {
      await auditService.logFromRequest(req, 'COMPLIANCE_REPORT_PUBLISHED', {
        reportId: id,
        success: true,
      });
    }

    logger.info('Compliance report published', { reportId: id });

    return updated;
  }

  /**
   * EN: Get GDPR report for user (data export)
   * VI: Lấy báo cáo GDPR cho user (export dữ liệu)
   */
  async getGDPRReport(userId: string): Promise<any> {
    const user = await this.prisma.user.findUnique({
      where: { id: userId },
      include: {
        profile: true,
        userRoles: {
          include: { role: true },
        },
        authEvents: {
          take: 100,
          orderBy: { timestamp: 'desc' },
        },
      },
    });

    if (!user) {
      throw new NotFoundError('User');
    }

    return {
      userId: user.id,
      email: user.email,
      username: user.username,
      profile: user.profile,
      roles: user.userRoles.map((ur) => ur.role.name),
      activity: user.authEvents,
      exportedAt: new Date(),
    };
  }
}

export const complianceService = new ComplianceService();
