import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { TetardCoinService } from '../economy/tetard-coin.service';
import { ConversionService } from '../economy/conversion.service';
import { ProcessedEvent } from './entities/processed-event.entity';

// Subscription tier rewards — economy-design.md
const SUB_TC: Record<string, number> = {
  '1000': 50,  // T1
  '2000': 120, // T2
  '3000': 350, // T3
  prime: 30,
};

// Bits threshold bonuses — economy-design.md
const BITS_BONUS: Array<{ threshold: number; bonus: number }> = [
  { threshold: 5000, bonus: 75 },
  { threshold: 1000, bonus: 15 },
  { threshold: 500, bonus: 5 },
];

@Injectable()
export class TwitchEventService {
  private readonly logger = new Logger(TwitchEventService.name);

  constructor(
    @InjectRepository(ProcessedEvent)
    private readonly processedRepo: Repository<ProcessedEvent>,
    private readonly tcService: TetardCoinService,
    private readonly conversionService: ConversionService,
  ) {}

  /**
   * Returns true if already processed (idempotence guard).
   * If not seen before, inserts and returns false.
   */
  async isAlreadyProcessed(messageId: string): Promise<boolean> {
    const existing = await this.processedRepo.findOne({ where: { id: messageId } });
    if (existing) return true;

    await this.processedRepo.save(this.processedRepo.create({ id: messageId }));
    return false;
  }

  /**
   * channel.cheer — convert bits to TC with threshold bonus, then earn.
   */
  async handleCheer(messageId: string, userId: string, bits: number): Promise<void> {
    if (await this.isAlreadyProcessed(messageId)) {
      this.logger.log(`Idempotent skip — messageId=${messageId}`);
      return;
    }

    const baseTC = this.conversionService.bitsToTC(bits);
    const bonus = this.getThresholdBonus(bits);
    const total = baseTC + bonus;

    await this.tcService.earn(userId, total, `cheer:${bits}bits`);
    this.logger.log(`Cheer processed: userId=${userId} bits=${bits} tc=${total} (base=${baseTC} bonus=${bonus})`);
  }

  /**
   * channel.subscribe / channel.subscription.gift
   * gifted: if true, gifter earns TC (senderUserId), recipient earns nothing.
   */
  async handleSubscription(
    messageId: string,
    userId: string,
    tier: string,
    gifted = false,
    gifterUserId?: string,
  ): Promise<void> {
    if (await this.isAlreadyProcessed(messageId)) {
      this.logger.log(`Idempotent skip — messageId=${messageId}`);
      return;
    }

    const tc = SUB_TC[tier] ?? SUB_TC['1000'];
    const earnUserId = gifted && gifterUserId ? gifterUserId : userId;
    const reason = gifted ? `gift-sub:tier${tier}` : `subscribe:tier${tier}`;

    await this.tcService.earn(earnUserId, tc, reason);
    this.logger.log(`Subscription processed: userId=${earnUserId} tier=${tier} tc=${tc} gifted=${gifted}`);
  }

  /**
   * Compute threshold bonus based on economy-design.md table.
   */
  getThresholdBonus(bits: number): number {
    for (const { threshold, bonus } of BITS_BONUS) {
      if (bits >= threshold) return bonus;
    }
    return 0;
  }
}
