import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import * as jwt from 'jsonwebtoken';
import { ConfigService } from '@nestjs/config';
import { AdminORM } from '../infrastructure/database/entities/admin.orm';
import { v4 as uuidv4 } from 'uuid';

/**
 * 管理员角色
 */
export enum AdminRole {
  SUPER_ADMIN = 'SUPER_ADMIN',
  ADMIN = 'ADMIN',
  OPERATOR = 'OPERATOR',
  VIEWER = 'VIEWER',
}

/**
 * 角色权限映射
 */
const ROLE_PERMISSIONS: Record<AdminRole, string[]> = {
  [AdminRole.SUPER_ADMIN]: ['*'],
  [AdminRole.ADMIN]: [
    'knowledge:*',
    'experience:*',
    'user:read',
    'conversation:read',
    'statistics:*',
    'admin:read',
  ],
  [AdminRole.OPERATOR]: [
    'knowledge:read',
    'knowledge:create',
    'knowledge:update',
    'experience:read',
    'experience:approve',
    'user:read',
    'conversation:read',
    'statistics:read',
  ],
  [AdminRole.VIEWER]: [
    'knowledge:read',
    'experience:read',
    'user:read',
    'conversation:read',
    'statistics:read',
  ],
};

/**
 * 登录结果
 */
export interface LoginResult {
  admin: {
    id: string;
    username: string;
    name: string;
    role: string;
    permissions: string[];
  };
  token: string;
  expiresIn: number;
}

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

  constructor(
    @InjectRepository(AdminORM)
    private adminRepo: Repository<AdminORM>,
    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.findOne({ where: { username } });

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

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

    // 更新登录信息
    admin.lastLoginAt = new Date();
    admin.lastLoginIp = ip;
    await this.adminRepo.save(admin);

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

    // 获取权限
    const permissions = this.getPermissions(admin.role as AdminRole, admin.permissions);

    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.findOne({ where: { id: decoded.sub } });
      if (!admin || !admin.isActive) {
        return { valid: false };
      }

      const permissions = this.getPermissions(admin.role as AdminRole, admin.permissions);

      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<AdminORM> {
    // 检查用户名是否存在
    const existing = await this.adminRepo.findOne({
      where: { username: params.username },
    });
    if (existing) {
      throw new Error('用户名已存在');
    }

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

    const admin = this.adminRepo.create({
      id: uuidv4(),
      username: params.username,
      passwordHash,
      name: params.name,
      email: params.email,
      phone: params.phone,
      role: params.role,
      permissions: ROLE_PERMISSIONS[params.role],
      isActive: true,
    });

    await this.adminRepo.save(admin);

    return admin;
  }

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

    const query = this.adminRepo.createQueryBuilder('admin');

    if (options?.role) {
      query.andWhere('admin.role = :role', { role: options.role });
    }

    if (options?.isActive !== undefined) {
      query.andWhere('admin.isActive = :active', { active: options.isActive });
    }

    query.orderBy('admin.createdAt', 'DESC');

    const [items, total] = await query
      .skip((page - 1) * pageSize)
      .take(pageSize)
      .getManyAndCount();

    return { items, total };
  }

  /**
   * 更新管理员
   */
  async updateAdmin(
    adminId: string,
    params: {
      name?: string;
      email?: string;
      phone?: string;
      role?: AdminRole;
      isActive?: boolean;
    },
  ): Promise<AdminORM> {
    const admin = await this.adminRepo.findOne({ where: { id: 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.role = params.role;
      admin.permissions = ROLE_PERMISSIONS[params.role];
    }
    if (params.isActive !== undefined) admin.isActive = params.isActive;

    await this.adminRepo.save(admin);

    return admin;
  }

  /**
   * 修改密码
   */
  async changePassword(
    adminId: string,
    oldPassword: string,
    newPassword: string,
  ): Promise<void> {
    const admin = await this.adminRepo.findOne({ where: { id: 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.save(admin);
  }

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

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

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

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

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

    return false;
  }

  /**
   * 获取管理员权限列表
   */
  private getPermissions(role: AdminRole, customPermissions?: string[]): string[] {
    const rolePermissions = ROLE_PERMISSIONS[role] || [];
    if (customPermissions && customPermissions.length > 0) {
      return [...new Set([...rolePermissions, ...customPermissions])];
    }
    return rolePermissions;
  }
}
