import { Injectable, UnauthorizedException, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { RedisService } from '../../infrastructure/redis/redis.service';
import * as bcrypt from 'bcrypt';
import * as jwt from 'jsonwebtoken';

@Injectable()
export class AuthService {
  private readonly logger = new Logger(AuthService.name);
  private readonly jwtSecret: string;
  private readonly jwtExpiresIn: string;

  constructor(
    private readonly prisma: PrismaService,
    private readonly redis: RedisService,
    private readonly configService: ConfigService,
  ) {
    this.jwtSecret = this.configService.get<string>('JWT_SECRET', 'admin-secret');
    this.jwtExpiresIn = this.configService.get<string>('JWT_EXPIRES_IN', '24h');
  }

  async login(username: string, password: string, ipAddress?: string, userAgent?: string): Promise<{ token: string; admin: any }> {
    const admin = await this.prisma.adminUser.findUnique({ where: { username } });
    if (!admin || admin.status !== 'ACTIVE') {
      throw new UnauthorizedException('Invalid credentials');
    }

    const isValid = await bcrypt.compare(password, admin.password);
    if (!isValid) {
      throw new UnauthorizedException('Invalid credentials');
    }

    const token = jwt.sign(
      { sub: admin.id, username: admin.username, role: admin.role },
      this.jwtSecret,
      { expiresIn: this.jwtExpiresIn as jwt.SignOptions['expiresIn'] },
    );

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

    await this.prisma.auditLog.create({
      data: { adminId: admin.id, action: 'LOGIN', resource: 'AUTH', ipAddress, userAgent },
    });

    return {
      token,
      admin: { id: admin.id, username: admin.username, name: admin.name, role: admin.role },
    };
  }

  async logout(adminId: string, ipAddress?: string, userAgent?: string): Promise<void> {
    await this.prisma.auditLog.create({
      data: { adminId, action: 'LOGOUT', resource: 'AUTH', ipAddress, userAgent },
    });
  }

  async createDefaultAdmin(): Promise<void> {
    const defaultUsername = this.configService.get<string>('DEFAULT_ADMIN_USERNAME', 'admin');
    const defaultPassword = this.configService.get<string>('DEFAULT_ADMIN_PASSWORD', 'admin123');

    const exists = await this.prisma.adminUser.findUnique({ where: { username: defaultUsername } });
    if (exists) return;

    const hashedPassword = await bcrypt.hash(defaultPassword, 10);
    await this.prisma.adminUser.create({
      data: { username: defaultUsername, password: hashedPassword, name: '超级管理员', role: 'SUPER_ADMIN' },
    });

    this.logger.log(`Default admin created: ${defaultUsername}`);
  }
}
