import { Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import * as bcrypt from 'bcrypt';
import { AuthToken } from '../entities/AuthToken';
import { LoginDto, RefreshTokenDto, LogoutDto } from '../dto/AuthDto';

// 导入Admin和Member服务
import { CoreAdminService } from '../../admin/services/core/CoreAdminService';
import { CoreMemberService } from '../../member/services/core/CoreMemberService';

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(AuthToken)
    private readonly authTokenRepository: Repository<AuthToken>,
    private readonly jwtService: JwtService,
    private readonly configService: ConfigService,
    private readonly adminService: CoreAdminService,
    private readonly memberService: CoreMemberService,
  ) {}

  /**
   * 管理员登录
   */
  async adminLogin(loginDto: LoginDto, ipAddress: string, userAgent: string) {
    const { username, password, siteId = 0 } = loginDto;

    // 调用AdminService验证用户名密码
    const adminUser = await this.validateAdminUser(username, password, siteId);
    
    if (!adminUser) {
      throw new UnauthorizedException('用户名或密码错误');
    }

    // 生成JWT Token
    const tokenPayload = {
      userId: adminUser.uid,
      username: adminUser.username,
      userType: 'admin',
      siteId,
    };

    const accessToken = this.jwtService.sign(tokenPayload, {
      expiresIn: this.configService.get('JWT_EXPIRES_IN', '7d'),
    });

    const refreshToken = this.jwtService.sign(tokenPayload, {
      expiresIn: this.configService.get('JWT_REFRESH_EXPIRES_IN', '30d'),
    });

    // 计算过期时间
    const expiresIn = this.configService.get('JWT_EXPIRES_IN', '7d');
    const refreshExpiresIn = this.configService.get('JWT_REFRESH_EXPIRES_IN', '30d');
    
    const expiresAt = this.calculateExpiryDate(expiresIn);
    const refreshExpiresAt = this.calculateExpiryDate(refreshExpiresIn);

    // 保存Token到数据库
    const authToken = this.authTokenRepository.create({
      token: accessToken,
      userId: adminUser.uid,
      userType: 'admin',
      siteId,
      expiresAt,
      refreshToken,
      refreshExpiresAt,
      ipAddress: ipAddress,
      userAgent: userAgent,
      deviceType: this.detectDeviceType(userAgent),
      isRevoked: 0,
    });

    await this.authTokenRepository.save(authToken);

    // 更新管理员登录信息
    await this.adminService.updateLoginInfo(adminUser.uid, ipAddress);

    return {
      accessToken,
      refreshToken,
      expiresIn,
      user: {
        userId: adminUser.uid,
        username: adminUser.username,
        realname: adminUser.real_name,
        userType: 'admin',
        siteId,
      },
    };
  }

  /**
   * 会员登录
   */
  async memberLogin(loginDto: LoginDto, ipAddress: string, userAgent: string) {
    const { username, password, siteId = 0 } = loginDto;

    // 调用MemberService验证用户名密码
    const memberUser = await this.validateMemberUser(username, password, siteId);
    
    if (!memberUser) {
      throw new UnauthorizedException('用户名或密码错误');
    }

    // 生成JWT Token
    const tokenPayload = {
      userId: memberUser.member_id,
      username: memberUser.username,
      userType: 'member',
      siteId,
    };

    const accessToken = this.jwtService.sign(tokenPayload, {
      expiresIn: this.configService.get('JWT_EXPIRES_IN', '7d'),
    });

    const refreshToken = this.jwtService.sign(tokenPayload, {
      expiresIn: this.configService.get('JWT_REFRESH_EXPIRES_IN', '30d'),
    });

    // 计算过期时间
    const expiresIn = this.configService.get('JWT_EXPIRES_IN', '7d');
    const refreshExpiresIn = this.configService.get('JWT_REFRESH_EXPIRES_IN', '30d');
    
    const expiresAt = this.calculateExpiryDate(expiresIn);
    const refreshExpiresAt = this.calculateExpiryDate(refreshExpiresIn);

    // 保存Token到数据库
    const authToken = this.authTokenRepository.create({
      token: accessToken,
      userId: memberUser.member_id,
      userType: 'member',
      siteId,
      expiresAt,
      refreshToken,
      refreshExpiresAt,
      ipAddress: ipAddress,
      userAgent: userAgent,
      deviceType: this.detectDeviceType(userAgent),
      isRevoked: 0,
    });

    await this.authTokenRepository.save(authToken);

    // 更新会员登录信息
    await this.memberService.updateLastLogin(memberUser.member_id, {
      ip: ipAddress,
      address: ipAddress, // 这里可以调用IP地址解析服务
      device: this.detectDeviceType(userAgent),
    });

    return {
      accessToken,
      refreshToken,
      expiresIn,
      user: {
        userId: memberUser.member_id,
        username: memberUser.username,
        nickname: memberUser.nickname,
        userType: 'member',
        siteId,
      },
    };
  }

  /**
   * 刷新Token
   */
  async refreshToken(refreshTokenDto: RefreshTokenDto) {
    const { refreshToken } = refreshTokenDto;

    try {
      // 验证刷新Token
      const payload = this.jwtService.verify(refreshToken);
      
      // 检查数据库中的Token记录
      const tokenRecord = await this.authTokenRepository.findOne({
        where: { refreshToken, isRevoked: 0 },
      });

      if (!tokenRecord || tokenRecord.isRefreshExpired()) {
        throw new UnauthorizedException('刷新Token无效或已过期');
      }

      // 生成新的访问Token
      const newTokenPayload = {
        userId: payload.userId,
        username: payload.username,
        userType: payload.userType,
        siteId: payload.siteId,
      };

      const newAccessToken = this.jwtService.sign(newTokenPayload, {
        expiresIn: this.configService.get('JWT_EXPIRES_IN', '7d'),
      });

      // 更新数据库中的Token
      tokenRecord.token = newAccessToken;
      tokenRecord.expiresAt = this.calculateExpiryDate(this.configService.get('JWT_EXPIRES_IN', '7d'));
      await this.authTokenRepository.save(tokenRecord);

      return {
        accessToken: newAccessToken,
        expiresIn: this.configService.get('JWT_EXPIRES_IN', '7d'),
      };
    } catch (error) {
      throw new UnauthorizedException('刷新Token无效');
    }
  }

  /**
   * 登出
   */
  async logout(logoutDto: LogoutDto) {
    const { token } = logoutDto;

    // 撤销Token
    const tokenRecord = await this.authTokenRepository.findOne({
      where: { token, isRevoked: 0 },
    });

    if (tokenRecord) {
      tokenRecord.isRevoked = 1;
      tokenRecord.revokedAt = new Date();
      tokenRecord.revokedReason = '用户主动登出';
      await this.authTokenRepository.save(tokenRecord);
    }

    return { message: '登出成功' };
  }

  /**
   * 验证Token
   */
  async validateToken(token: string): Promise<any> {
    try {
      // 验证JWT Token
      const payload = this.jwtService.verify(token);
      
      // 检查数据库中的Token记录
      const tokenRecord = await this.authTokenRepository.findOne({
        where: { token, isRevoked: 0 },
      });

      if (!tokenRecord || tokenRecord.isExpired()) {
        return null;
      }

      return payload;
    } catch (error) {
      return null;
    }
  }

  /**
   * 获取用户Token信息
   */
  async getUserTokens(userId: number, userType: string, siteId: number = 0) {
    return await this.authTokenRepository.find({
      where: { userId, userType, siteId, isRevoked: 0 },
      order: { createdAt: 'DESC' },
    });
  }

  /**
   * 撤销用户所有Token
   */
  async revokeUserTokens(userId: number, userType: string, siteId: number = 0, reason: string = '管理员撤销') {
    const tokens = await this.authTokenRepository.find({
      where: { userId, userType, siteId, isRevoked: 0 },
    });

    for (const token of tokens) {
      token.isRevoked = 1;
      token.revokedAt = new Date();
      token.revokedReason = reason;
    }

    await this.authTokenRepository.save(tokens);
    return { message: 'Token撤销成功', count: tokens.length };
  }

  /**
   * 清理过期Token
   */
  async cleanupExpiredTokens() {
    const expiredTokens = await this.authTokenRepository
      .createQueryBuilder('token')
      .where('token.expires_at < :now', { now: new Date() })
      .andWhere('token.is_revoked = :revoked', { revoked: 0 })
      .getMany();

    for (const token of expiredTokens) {
      token.isRevoked = 1;
      token.revokedAt = new Date();
      token.revokedReason = 'Token过期自动清理';
    }

    if (expiredTokens.length > 0) {
      await this.authTokenRepository.save(expiredTokens);
    }

    return { message: '过期Token清理完成', count: expiredTokens.length };
  }

  /**
   * 计算过期时间
   */
  private calculateExpiryDate(expiresIn: string): Date {
    const now = new Date();
    const unit = expiresIn.slice(-1);
    const value = parseInt(expiresIn.slice(0, -1));

    switch (unit) {
      case 's':
        return new Date(now.getTime() + value * 1000);
      case 'm':
        return new Date(now.getTime() + value * 60 * 1000);
      case 'h':
        return new Date(now.getTime() + value * 60 * 60 * 1000);
      case 'd':
        return new Date(now.getTime() + value * 24 * 60 * 60 * 1000);
      default:
        return new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000); // 默认7天
    }
  }

  /**
   * 检测设备类型
   */
  private detectDeviceType(userAgent: string): string {
    if (/mobile|android|iphone|ipad|phone/i.test(userAgent)) {
      return 'mobile';
    } else if (/app|application/i.test(userAgent)) {
      return 'app';
    } else {
      return 'web';
    }
  }

  /**
   * 验证管理员用户
   */
  private async validateAdminUser(username: string, password: string, siteId: number): Promise<any> {
    try {
      // 根据用户名查找管理员
      const admin = await this.adminService.getAdminByUsername(username);
      if (!admin) {
        return null;
      }

      // 验证密码
      const isValidPassword = await this.adminService.validatePassword(admin.uid, password);
      if (!isValidPassword) {
        return null;
      }

      // 检查状态
      if (admin.status !== 1 || admin.is_del !== 0) {
        return null;
      }

      return admin;
    } catch (error) {
      return null;
    }
  }

  /**
   * 验证会员用户
   */
  private async validateMemberUser(username: string, password: string, siteId: number): Promise<any> {
    try {
      // 根据用户名查找会员
      let member = await this.memberService.findByUsername(username);
      
      // 如果用户名没找到，尝试用手机号或邮箱查找
      if (!member) {
        member = await this.memberService.findByMobile(username);
      }
      if (!member) {
        member = await this.memberService.findByEmail(username);
      }

      if (!member) {
        return null;
      }

      // 验证密码
      const isValidPassword = await bcrypt.compare(password, member.password);
      if (!isValidPassword) {
        return null;
      }

      // 检查状态
      if (member.status !== 1 || member.is_del !== 0) {
        return null;
      }

      return member;
    } catch (error) {
      return null;
    }
  }
} 