import { Injectable, Logger, NotFoundException, BadRequestException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';

const ALL_CAPABILITIES = [
  'LOGIN', 'TRADING', 'C2C', 'TRANSFER_IN', 'TRANSFER_OUT',
  'P2P_SEND', 'P2P_RECEIVE', 'MINING_CLAIM', 'KYC',
  'PROFILE_EDIT', 'VIEW_ASSET', 'VIEW_TEAM', 'VIEW_RECORDS',
] as const;

export interface CapabilityItem {
  capability: string;
  enabled: boolean;
  reason?: string;
  disabledBy?: string;
  disabledAt?: string;
  expiresAt?: string;
}

export interface SetCapabilityDto {
  capability: string;
  enabled: boolean;
  reason?: string;
  expiresAt?: string; // ISO 8601
}

export interface CapabilityLogItem {
  id: string;
  accountSequence: string;
  capability: string;
  action: string;
  reason?: string;
  operatorId?: string;
  previousValue: boolean;
  newValue: boolean;
  expiresAt?: string;
  createdAt: string;
}

@Injectable()
export class CapabilityAdminService {
  private readonly logger = new Logger(CapabilityAdminService.name);
  private readonly authServiceUrl: string;

  constructor(
    private readonly prisma: PrismaService,
    private readonly configService: ConfigService,
  ) {
    this.authServiceUrl = this.configService.get<string>(
      'AUTH_SERVICE_URL',
      'http://localhost:3010',
    );
  }

  /**
   * 获取用户能力列表
   */
  async getCapabilities(accountSequence: string): Promise<CapabilityItem[]> {
    const url = `${this.authServiceUrl}/api/v2/internal/capabilities/${accountSequence}`;

    try {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`auth-service responded with ${response.status}`);
      }

      const result = await response.json();
      const data = result.data || result;

      // 将 { LOGIN: true, C2C: false, ... } 转成详细列表
      if (Array.isArray(data)) {
        return data;
      }

      // 如果返回的是 map 格式，转换成列表
      return ALL_CAPABILITIES.map((cap) => ({
        capability: cap,
        enabled: data[cap] !== false,
      }));
    } catch (error: any) {
      this.logger.error(`获取用户能力失败: ${error.message}`);
      // fallback: 返回全部开启
      return ALL_CAPABILITIES.map((cap) => ({
        capability: cap,
        enabled: true,
      }));
    }
  }

  /**
   * 设置单个能力
   */
  async setCapability(
    accountSequence: string,
    dto: SetCapabilityDto,
    adminId: string,
    ipAddress?: string,
    userAgent?: string,
  ): Promise<CapabilityItem[]> {
    if (!ALL_CAPABILITIES.includes(dto.capability as any)) {
      throw new BadRequestException(`无效的能力: ${dto.capability}`);
    }

    const url = `${this.authServiceUrl}/api/v2/internal/capabilities/${accountSequence}`;

    try {
      const response = await fetch(url, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          capability: dto.capability,
          enabled: dto.enabled,
          reason: dto.reason,
          operatorId: adminId,
          expiresAt: dto.expiresAt,
        }),
      });

      if (!response.ok) {
        const errBody = await response.text();
        throw new Error(`auth-service responded with ${response.status}: ${errBody}`);
      }

      // 写本地审计日志
      await this.writeAuditLog(adminId, accountSequence, dto, ipAddress, userAgent);

      // 返回最新能力列表
      return this.getCapabilities(accountSequence);
    } catch (error: any) {
      if (error instanceof BadRequestException) throw error;
      this.logger.error(`设置用户能力失败: ${error.message}`);
      throw new BadRequestException(`设置用户能力失败: ${error.message}`);
    }
  }

  /**
   * 批量设置能力
   */
  async setCapabilities(
    accountSequence: string,
    items: SetCapabilityDto[],
    adminId: string,
    ipAddress?: string,
    userAgent?: string,
  ): Promise<CapabilityItem[]> {
    // 验证所有能力
    for (const item of items) {
      if (!ALL_CAPABILITIES.includes(item.capability as any)) {
        throw new BadRequestException(`无效的能力: ${item.capability}`);
      }
    }

    const url = `${this.authServiceUrl}/api/v2/internal/capabilities/${accountSequence}/bulk`;

    try {
      const response = await fetch(url, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          capabilities: items.map((item) => ({
            capability: item.capability,
            enabled: item.enabled,
            reason: item.reason,
            expiresAt: item.expiresAt,
          })),
          operatorId: adminId,
        }),
      });

      if (!response.ok) {
        const errBody = await response.text();
        throw new Error(`auth-service responded with ${response.status}: ${errBody}`);
      }

      // 写本地审计日志
      for (const item of items) {
        await this.writeAuditLog(adminId, accountSequence, item, ipAddress, userAgent);
      }

      return this.getCapabilities(accountSequence);
    } catch (error: any) {
      if (error instanceof BadRequestException) throw error;
      this.logger.error(`批量设置用户能力失败: ${error.message}`);
      throw new BadRequestException(`批量设置用户能力失败: ${error.message}`);
    }
  }

  /**
   * 获取能力变更日志
   */
  async getCapabilityLogs(
    accountSequence: string,
    page: number = 1,
    pageSize: number = 20,
  ): Promise<{ data: CapabilityLogItem[]; total: number; page: number; pageSize: number }> {
    const url = `${this.authServiceUrl}/api/v2/internal/capabilities/${accountSequence}/logs?page=${page}&pageSize=${pageSize}`;

    try {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(`auth-service responded with ${response.status}`);
      }

      const result = await response.json();
      const data = result.data || result;

      return {
        data: data.data || [],
        total: data.total || 0,
        page,
        pageSize,
      };
    } catch (error: any) {
      this.logger.error(`获取能力变更日志失败: ${error.message}`);
      return { data: [], total: 0, page, pageSize };
    }
  }

  /**
   * 写本地审计日志
   */
  private async writeAuditLog(
    adminId: string,
    accountSequence: string,
    dto: SetCapabilityDto,
    ipAddress?: string,
    userAgent?: string,
  ): Promise<void> {
    try {
      await this.prisma.auditLog.create({
        data: {
          adminId,
          action: dto.enabled ? 'ENABLE' : 'DISABLE',
          resource: 'CAPABILITY',
          resourceId: `${accountSequence}:${dto.capability}`,
          newValue: {
            capability: dto.capability,
            enabled: dto.enabled,
            reason: dto.reason || null,
            expiresAt: dto.expiresAt || null,
          },
          ipAddress,
          userAgent,
        },
      });
    } catch (error: any) {
      this.logger.warn(`写审计日志失败: ${error.message}`);
    }
  }
}
