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

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

/**
 * EN: Policy Governance Service
 * VI: Service quản trị policy
 */
export class PolicyGovernanceService {
  private prisma: PrismaClient;

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

  /**
   * EN: Create policy template
   * VI: Tạo template policy
   */
  async createTemplate(data: CreatePolicyTemplateDto, req?: Request): Promise<any> {
    const template = await this.prisma.policyTemplate.create({
      data: {
        name: data.name,
        category: data.category,
        description: data.description,
        content: data.content,
        version: data.version || '1.0.0',
        isActive: true,
      },
    });

    if (req) {
      await auditService.logFromRequest(req, 'POLICY_TEMPLATE_CREATED', {
        templateId: template.id,
        success: true,
      });
    }

    logger.info('Policy template created', { templateId: template.id });

    return template;
  }

  /**
   * EN: Get templates
   * VI: Lấy các template
   */
  async getTemplates(category?: PolicyCategory): Promise<any[]> {
    const where: any = { isActive: true };
    if (category) {
      where.category = category;
    }

    return this.prisma.policyTemplate.findMany({
      where,
      orderBy: { createdAt: 'desc' },
    });
  }

  /**
   * EN: Create policy from template
   * VI: Tạo policy từ template
   */
  async createPolicyFromTemplate(
    templateId: string,
    data: CreatePolicyFromTemplateDto,
    req?: Request
  ): Promise<any> {
    const template = await this.prisma.policyTemplate.findUnique({
      where: { id: templateId },
    });

    if (!template) {
      throw new NotFoundError('Policy Template');
    }

    // Merge template content with provided data
    // EN: Ensure both are objects before spreading
    // VI: Đảm bảo cả hai đều là objects trước khi spread
    const templateContent = typeof template.content === 'object' && template.content !== null
      ? template.content as Record<string, any>
      : {};
    const conditionData = typeof data.condition === 'object' && data.condition !== null
      ? data.condition as Record<string, any>
      : {};
    const policyData = {
      ...templateContent,
      ...conditionData,
    };

    const policy = await this.prisma.policy.create({
      data: {
        name: data.name,
        description: data.description,
        resource: data.resource,
        condition: policyData,
        effect: data.effect,
        priority: data.priority || 0,
        organizationId: data.organizationId || null,
        isActive: true,
      },
    });

    if (req) {
      await auditService.logFromRequest(req, 'POLICY_CREATED_FROM_TEMPLATE', {
        policyId: policy.id,
        templateId,
        success: true,
      });
    }

    logger.info('Policy created from template', { policyId: policy.id, templateId });

    return policy;
  }

  /**
   * EN: Get policy versions (placeholder - would require versioning table)
   * VI: Lấy các phiên bản policy (placeholder - cần bảng versioning)
   */
  async getPolicyVersions(policyId: string): Promise<any[]> {
    const policy = await this.prisma.policy.findUnique({ where: { id: policyId } });
    if (!policy) {
      throw new NotFoundError('Policy');
    }

    // TODO: Implement policy versioning with a separate table
    // For now, return single version
    return [
      {
        version: '1.0.0',
        policy,
        createdAt: policy.createdAt,
        updatedAt: policy.updatedAt,
      },
    ];
  }

  /**
   * EN: Test policy
   * VI: Test policy
   */
  async testPolicy(policyId: string, testData: any, req?: Request): Promise<any> {
    const policy = await this.prisma.policy.findUnique({ where: { id: policyId } });
    if (!policy) {
      throw new NotFoundError('Policy');
    }

    // TODO: Implement actual policy testing logic
    // This would evaluate the policy condition against testData
    const result = {
      policyId: policy.id,
      testData,
      evaluation: 'ALLOW', // Placeholder
      matched: true,
      testedAt: new Date(),
    };

    if (req) {
      await auditService.logFromRequest(req, 'POLICY_TESTED', {
        policyId,
        success: true,
      });
    }

    return result;
  }

  /**
   * EN: Validate policy
   * VI: Validate policy
   */
  async validatePolicy(policy: any): Promise<{ valid: boolean; errors: string[] }> {
    const errors: string[] = [];

    if (!policy.resource || typeof policy.resource !== 'string') {
      errors.push('Resource is required / Resource là bắt buộc');
    }

    if (!policy.condition || typeof policy.condition !== 'object') {
      errors.push('Condition is required / Condition là bắt buộc');
    }

    if (!policy.effect || !['ALLOW', 'DENY'].includes(policy.effect)) {
      errors.push('Effect must be ALLOW or DENY / Effect phải là ALLOW hoặc DENY');
    }

    return {
      valid: errors.length === 0,
      errors,
    };
  }
}

export const policyGovernanceService = new PolicyGovernanceService();
