import { Injectable } from '@nestjs/common';
import { RedisService } from '../../infra/redis.service';
import { SettingsService } from '../settings.service';

@Injectable()
export class BotRateLimitService {
  constructor(
    private readonly redis: RedisService,
    private readonly settings: SettingsService
  ) {}

  async assertCanCreateBot(ownerId: string) {
    const maxBots = await this.settings.getNumber('BOT_MAX_BOTS_PER_USER', 5);
    const key = `bot:create:count:${ownerId}`;
    const cached = await this.redis.client.get(key);
    if (cached) {
      const count = Number(cached);
      if (Number.isFinite(count) && count >= maxBots) {
        return { allowed: false as const, reason: `Достигнут лимит ботов (${maxBots})` };
      }
    }
    return { allowed: true as const, maxBots };
  }

  async syncOwnerBotCount(ownerId: string, count: number) {
    await this.redis.client.set(`bot:create:count:${ownerId}`, String(count), 'EX', 300);
  }

  async assertBotApiRateLimit(tokenHash: string) {
    const limit = await this.settings.getNumber('BOT_API_RATE_LIMIT_PER_SECOND', 30);
    const key = `bot:api:rate:${tokenHash}`;
    const count = await this.redis.client.incr(key);
    if (count === 1) {
      await this.redis.client.expire(key, 1);
    }
    if (count > limit) {
      const retryAfter = Math.max(await this.redis.client.ttl(key), 1);
      return { allowed: false as const, retryAfter };
    }
    return { allowed: true as const };
  }

  async cacheValidatedBot(tokenHash: string, payload: Record<string, unknown>) {
    await this.redis.client.set(`bot:token:${tokenHash}`, JSON.stringify(payload), 'EX', 300);
  }

  async getCachedValidatedBot(tokenHash: string) {
    const cached = await this.redis.client.get(`bot:token:${tokenHash}`);
    return cached ? (JSON.parse(cached) as Record<string, unknown>) : null;
  }

  async invalidateTokenCache(tokenHash: string) {
    await this.redis.client.del(`bot:token:${tokenHash}`);
  }
}
