import { Injectable, Inject } from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import * as jwt from 'jsonwebtoken';
import { ConfigService } from '@nestjs/config';
import { AdminEntity } from '../../domain/entities/admin.entity';
import { AdminRole, ROLE_PERMISSIONS } from '../../domain/value-objects/admin-role.enum';
import { IAdminRepository, ADMIN_REPOSITORY } from '../../domain/repositories/admin.repository.interface';
import { LoginResult } from '../dtos/admin.dto';

/**
 * 管理员服务
 */
@Injectable()
export class AdminService {
  private readonly jwtSecret: string;
  private readonly jwtExpiresIn: number = 24 * 60 * 60; // 24小时

  constructor(
    @Inject(ADMIN_REPOSITORY)
    private adminRepo: IAdminRepository,
    private configService: ConfigService,
  ) {
    this.jwtSecret = this.configService.get('JWT_SECRET') || 'iconsulting-secret-key';
  }

  /**
   * 管理员登录
   */
  async login(username: string, password: string, ip?: string): Promise<LoginResult> {
    const admin = await this.adminRepo.findByUsername(username);

    if (!admin || !admin.isActive) {
      throw new Error('用户名或密码错误');
    }

    const isPasswordValid = await bcrypt.compare(password, admin.passwordHash);
    if (!isPasswordValid) {
      throw new Error('用户名或密码错误');
    }

    // 更新登录信息
    admin.recordLogin(ip);
    await this.adminRepo.update(admin);

    // 生成Token
    const token = jwt.sign(
      {
        sub: admin.id,
        username: admin.username,
        role: admin.role,
      },
      this.jwtSecret,
      { expiresIn: this.jwtExpiresIn },
    );

    // 获取权限
    const permissions = admin.getPermissions();

    return {
      admin: {
        id: admin.id,
        username: admin.username,
        name: admin.name,
        role: admin.role,
        permissions,
      },
      token,
      expiresIn: this.jwtExpiresIn,
    };
  }

  /**
   * 验证Token
   */
  async verifyToken(token: string): Promise<{
    valid: boolean;
    admin?: {
      id: string;
      username: string;
      role: string;
      permissions: string[];
    };
  }> {
    try {
      const decoded = jwt.verify(token, this.jwtSecret) as {
        sub: string;
        username: string;
        role: string;
      };

      const admin = await this.adminRepo.findById(decoded.sub);
      if (!admin || !admin.isActive) {
        return { valid: false };
      }

      const permissions = admin.getPermissions();

      return {
        valid: true,
        admin: {
          id: admin.id,
          username: admin.username,
          role: admin.role,
          permissions,
        },
      };
    } catch {
      return { valid: false };
    }
  }

  /**
   * 创建管理员
   */
  async createAdmin(params: {
    username: string;
    password: string;
    name: string;
    email?: string;
    phone?: string;
    role: AdminRole;
  }): Promise<AdminEntity> {
    // 检查用户名是否存在
    const existing = await this.adminRepo.findByUsername(params.username);
    if (existing) {
      throw new Error('用户名已存在');
    }

    // 加密密码
    const passwordHash = await bcrypt.hash(params.password, 10);

    const admin = AdminEntity.create({
      username: params.username,
      passwordHash,
      name: params.name,
      email: params.email,
      phone: params.phone,
      role: params.role,
    });

    await this.adminRepo.save(admin);

    return admin;
  }

  /**
   * 获取管理员列表
   */
  async listAdmins(options?: {
    role?: AdminRole;
    isActive?: boolean;
    page?: number;
    pageSize?: number;
  }): Promise<{
    items: AdminEntity[];
    total: number;
  }> {
    const page = options?.page || 1;
    const pageSize = options?.pageSize || 20;

    const [items, total] = await Promise.all([
      this.adminRepo.findAll({
        role: options?.role,
        isActive: options?.isActive,
        limit: pageSize,
        offset: (page - 1) * pageSize,
      }),
      this.adminRepo.count({
        role: options?.role,
        isActive: options?.isActive,
      }),
    ]);

    return { items, total };
  }

  /**
   * 更新管理员
   */
  async updateAdmin(
    adminId: string,
    params: {
      name?: string;
      email?: string;
      phone?: string;
      role?: AdminRole;
      isActive?: boolean;
    },
  ): Promise<AdminEntity> {
    const admin = await this.adminRepo.findById(adminId);
    if (!admin) {
      throw new Error('管理员不存在');
    }

    if (params.name) admin.name = params.name;
    if (params.email !== undefined) admin.email = params.email;
    if (params.phone !== undefined) admin.phone = params.phone;
    if (params.role) admin.updateRole(params.role);
    if (params.isActive !== undefined) admin.isActive = params.isActive;

    await this.adminRepo.update(admin);

    return admin;
  }

  /**
   * 修改密码
   */
  async changePassword(
    adminId: string,
    oldPassword: string,
    newPassword: string,
  ): Promise<void> {
    const admin = await this.adminRepo.findById(adminId);
    if (!admin) {
      throw new Error('管理员不存在');
    }

    const isOldPasswordValid = await bcrypt.compare(oldPassword, admin.passwordHash);
    if (!isOldPasswordValid) {
      throw new Error('原密码错误');
    }

    admin.passwordHash = await bcrypt.hash(newPassword, 10);
    await this.adminRepo.update(admin);
  }

  /**
   * 重置密码（超管功能）
   */
  async resetPassword(adminId: string, newPassword: string): Promise<void> {
    const admin = await this.adminRepo.findById(adminId);
    if (!admin) {
      throw new Error('管理员不存在');
    }

    admin.passwordHash = await bcrypt.hash(newPassword, 10);
    await this.adminRepo.update(admin);
  }

  /**
   * 检查权限
   */
  hasPermission(adminPermissions: string[], requiredPermission: string): boolean {
    // 超管拥有所有权限
    if (adminPermissions.includes('*')) {
      return true;
    }

    // 完全匹配
    if (adminPermissions.includes(requiredPermission)) {
      return true;
    }

    // 通配符匹配 (如 knowledge:* 匹配 knowledge:read)
    const [resource] = requiredPermission.split(':');
    if (adminPermissions.includes(`${resource}:*`)) {
      return true;
    }

    return false;
  }
}
