import {
  Injectable,
  NotFoundException,
  ConflictException,
  BadRequestException,
} from '@nestjs/common';
import { PrismaService } from '../../infrastructure/database/prisma.service';
import { PasswordService } from '../../common/utils/password.service';
import { AdminAuditService } from '../admin-auth/admin-audit.service';
import { CreateAdminUserDto } from './dto/create-admin-user.dto';
import { UpdateAdminUserDto } from './dto/update-admin-user.dto';
import { QueryAdminUsersDto } from './dto/query-admin-users.dto';
import { AdminRole } from '../../common/types/admin-role.enum';

@Injectable()
export class AdminUsersService {
  constructor(
    private readonly prisma: PrismaService,
    private readonly passwordService: PasswordService,
    private readonly auditService: AdminAuditService,
  ) {}

  async list(query: QueryAdminUsersDto) {
    const page = query.page ?? 1;
    const limit = query.limit ?? 20;
    const skip = (page - 1) * limit;

    const where: any = { deletedAt: null };

    if (query.search) {
      where.OR = [
        { email: { contains: query.search } },
        { displayName: { contains: query.search } },
      ];
    }
    if (query.role) {
      where.role = query.role;
    }
    if (query.status) {
      where.status = query.status;
    }

    const [items, total] = await Promise.all([
      this.prisma.adminUser.findMany({
        where,
        skip,
        take: limit,
        orderBy: { createdAt: 'desc' },
        select: {
          id: true,
          email: true,
          displayName: true,
          role: true,
          status: true,
          twoFactorEnabled: true,
          lastLoginAt: true,
          lastLoginIp: true,
          createdAt: true,
        },
      }),
      this.prisma.adminUser.count({ where }),
    ]);

    return {
      items,
      total,
      page,
      limit,
      totalPages: Math.ceil(total / limit),
    };
  }

  async getById(id: string) {
    const admin = await this.prisma.adminUser.findFirst({
      where: { id, deletedAt: null },
      select: {
        id: true,
        email: true,
        displayName: true,
        role: true,
        status: true,
        twoFactorEnabled: true,
        lastLoginAt: true,
        lastLoginIp: true,
        createdAt: true,
      },
    });
    if (!admin) throw new NotFoundException('管理员不存在');
    return admin;
  }

  async create(
    dto: CreateAdminUserDto,
    operatorId: string,
    ip?: string,
    userAgent?: string,
  ) {
    const existing = await this.prisma.adminUser.findUnique({
      where: { email: dto.email },
    });
    if (existing) throw new ConflictException('邮箱已被使用');

    const passwordHash = await this.passwordService.hash(dto.password);
    const admin = await this.prisma.adminUser.create({
      data: {
        email: dto.email,
        passwordHash,
        displayName: dto.displayName,
        role: dto.role,
      },
      select: {
        id: true,
        email: true,
        displayName: true,
        role: true,
        status: true,
        twoFactorEnabled: true,
        lastLoginAt: true,
        lastLoginIp: true,
        createdAt: true,
      },
    });

    await this.auditService.log({
      adminUserId: operatorId,
      action: 'CREATE_ADMIN',
      resourceType: 'AdminUser',
      resourceId: admin.id,
      afterJson: { email: dto.email, role: dto.role },
      ip,
      userAgent,
    });

    return admin;
  }

  async update(
    id: string,
    dto: UpdateAdminUserDto,
    operatorId: string,
    ip?: string,
    userAgent?: string,
  ) {
    const admin = await this.prisma.adminUser.findFirst({
      where: { id, deletedAt: null },
    });
    if (!admin) throw new NotFoundException('管理员不存在');

    if (dto.role && !Object.values(AdminRole).includes(dto.role as AdminRole)) {
      throw new BadRequestException('无效的角色');
    }
    if (dto.status && !['ACTIVE', 'DISABLED'].includes(dto.status)) {
      throw new BadRequestException('无效的状态');
    }

    const beforeJson = { role: admin.role, status: admin.status };

    const updated = await this.prisma.adminUser.update({
      where: { id },
      data: {
        ...(dto.role && { role: dto.role }),
        ...(dto.status && { status: dto.status }),
        ...(dto.displayName && { displayName: dto.displayName }),
      },
      select: {
        id: true,
        email: true,
        displayName: true,
        role: true,
        status: true,
        twoFactorEnabled: true,
        lastLoginAt: true,
        lastLoginIp: true,
        createdAt: true,
      },
    });

    await this.auditService.log({
      adminUserId: operatorId,
      action: 'UPDATE_ADMIN',
      resourceType: 'AdminUser',
      resourceId: id,
      beforeJson,
      afterJson: { role: updated.role, status: updated.status },
      ip,
      userAgent,
    });

    return updated;
  }

  async delete(
    id: string,
    operatorId: string,
    ip?: string,
    userAgent?: string,
  ) {
    const admin = await this.prisma.adminUser.findFirst({
      where: { id, deletedAt: null },
    });
    if (!admin) throw new NotFoundException('管理员不存在');

    if (admin.role === 'SUPER_ADMIN') {
      throw new BadRequestException('不可删除超级管理员');
    }

    await this.prisma.adminUser.update({
      where: { id },
      data: { deletedAt: new Date() },
    });

    await this.auditService.log({
      adminUserId: operatorId,
      action: 'DELETE_ADMIN',
      resourceType: 'AdminUser',
      resourceId: id,
      beforeJson: { email: admin.email, role: admin.role },
      ip,
      userAgent,
    });
  }
}
