import { Injectable, Logger } from '@nestjs/common';
import * as crypto from 'crypto';
import { VERIFICATION_CONFIG } from 'src/common/config/VerificationConfig';

/**
 * 인증번호 생성 및 검증 서비스 (메모리 기반)
 */
@Injectable()
export class VerificationService {
  private readonly logger = new Logger(VerificationService.name);
  
  // 메모리 저장소 (key -> { code, expiresAt })
  private readonly store = new Map<string, { value: string; expiresAt: number }>();

  constructor() {
    this.logger.log(`[VERIFY] VerificationService 초기화 (메모리 모드)`);
    
    // 만료된 항목 정리 (1분마다)
    setInterval(() => this.cleanup(), 60000);
  }

  /**
   * 만료된 항목 정리
   */
  private cleanup(): void {
    const now = Date.now();
    let cleaned = 0;
    
    for (const [key, data] of this.store.entries()) {
      if (data.expiresAt < now) {
        this.store.delete(key);
        cleaned++;
      }
    }
    
    if (cleaned > 0) {
      this.logger.debug(`[VERIFY] 만료된 ${cleaned}개 항목 정리됨`);
    }
  }

  /**
   * 6자리 인증번호 생성
   */
  generateCode(): string {
    const code = Math.floor(100000 + Math.random() * 900000).toString();
    this.logger.log(`[VERIFY] 인증번호 생성: ${code}`);
    return code;
  }

  /**
   * 인증번호 저장 (TTL 적용)
   */
  async saveCode(key: string, code: string): Promise<void> {
    const expiresAt = Date.now() + (VERIFICATION_CONFIG.CODE_EXPIRY_SECONDS * 1000);
    
    this.store.set(key, { value: code, expiresAt });
    
    this.logger.log(`[VERIFY] 코드 저장 - Key: ${key}, TTL: ${VERIFICATION_CONFIG.CODE_EXPIRY_SECONDS}초`);
  }

  /**
   * 인증번호 검증
   */
  async verifyCode(key: string, code: string): Promise<boolean> {
    this.logger.log(`[VERIFY] 코드 검증 - Key: ${key}, Input: ${code}`);

    const data = this.store.get(key);

    if (!data) {
      this.logger.warn(`[VERIFY] 저장된 코드 없음 (만료 또는 미발급)`);
      return false;
    }

    // 만료 체크
    if (data.expiresAt < Date.now()) {
      this.logger.warn(`[VERIFY] 코드 만료됨`);
      this.store.delete(key);
      return false;
    }

    if (data.value !== code) {
      this.logger.warn(`[VERIFY] 코드 불일치 - Saved: ${data.value}, Input: ${code}`);
      return false;
    }

    // 검증 성공 시 삭제 (1회용)
    this.store.delete(key);
    this.logger.log(`[VERIFY] 검증 성공, 코드 삭제됨`);
    return true;
  }

  /**
   * 비밀번호 재설정 토큰 생성 및 저장
   */
  async generateResetToken(userId: string): Promise<string> {
    this.logger.log(`[VERIFY] 리셋 토큰 생성 - userId: ${userId}`);
    
    const token = crypto.randomBytes(VERIFICATION_CONFIG.TOKEN_BYTES_LENGTH).toString('hex');
    const expiresAt = Date.now() + (VERIFICATION_CONFIG.RESET_TOKEN_EXPIRY_SECONDS * 1000);
    
    this.store.set(`reset:${token}`, { value: userId, expiresAt });
    
    this.logger.log(`[VERIFY] 리셋 토큰 저장 완료`);
    return token;
  }

  /**
   * 비밀번호 재설정 토큰 검증
   */
  async verifyResetToken(token: string): Promise<string | null> {
    this.logger.log(`[VERIFY] 리셋 토큰 검증`);

    const key = `reset:${token}`;
    const data = this.store.get(key);

    if (!data) {
      this.logger.warn(`[VERIFY] 리셋 토큰 없음 또는 만료`);
      return null;
    }

    if (data.expiresAt < Date.now()) {
      this.logger.warn(`[VERIFY] 리셋 토큰 만료됨`);
      this.store.delete(key);
      return null;
    }

    this.store.delete(key);
    this.logger.log(`[VERIFY] 리셋 토큰 검증 성공 - userId: ${data.value}`);
    return data.value;
  }
}
