import {
  Injectable,
  ConflictException,
  NotFoundException,
  BadRequestException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Character } from './entities/character.entity';
import { LevelThreshold } from './entities/level-threshold.entity';
import { CreateCharacterDto } from './dto/create-character.dto';
import { User } from '../user/user.entity';

const STAT_POOL = 10; // 5 stats × 1 base + 5 points à distribuer
const ENDURANCE_REGEN_MINUTES = 6; // 1 pt d'endurance toutes les 6 min = 10 pts/heure

@Injectable()
export class CharacterService {
  constructor(
    @InjectRepository(Character)
    private readonly characterRepository: Repository<Character>,
    @InjectRepository(LevelThreshold)
    private readonly levelThresholdRepository: Repository<LevelThreshold>,
  ) {}

  // Pattern lazy calculation — pas de timer actif
  private calculateEndurance(character: Character): number {
    const elapsedMinutes =
      (Date.now() - character.lastEnduranceTs.getTime()) / 60_000;
    const recharge = Math.floor(elapsedMinutes / ENDURANCE_REGEN_MINUTES);
    return Math.min(character.enduranceSaved + recharge, character.enduranceMax);
  }

  async create(dto: CreateCharacterDto, user: User): Promise<Character & { enduranceCurrent: number }> {
    const totalStats =
      dto.force + dto.agilite + dto.intelligence + dto.chance + dto.vitalite;

    if (totalStats !== STAT_POOL) {
      throw new BadRequestException(
        `La somme des stats doit être égale à ${STAT_POOL} (reçu : ${totalStats})`,
      );
    }

    const existing = await this.characterRepository.findOne({
      where: { userId: user.id },
    });
    if (existing) {
      throw new ConflictException('Ce joueur possède déjà un personnage');
    }

    const character = this.characterRepository.create({
      userId: user.id,
      name: dto.name,
      force: dto.force,
      agilite: dto.agilite,
      intelligence: dto.intelligence,
      chance: dto.chance,
      vitalite: dto.vitalite,
      enduranceSaved: 100,
      lastEnduranceTs: new Date(),
      enduranceMax: 100,
    });

    const saved = await this.characterRepository.save(character);
    return { ...saved, enduranceCurrent: this.calculateEndurance(saved) };
  }

  async findByUser(user: User): Promise<Character & { enduranceCurrent: number }> {
    const character = await this.characterRepository.findOne({
      where: { userId: user.id },
    });

    if (!character) {
      throw new NotFoundException('Aucun personnage trouvé pour ce joueur');
    }

    return { ...character, enduranceCurrent: this.calculateEndurance(character) };
  }

  async getEndurance(
    user: User,
  ): Promise<{ enduranceCurrent: number; enduranceMax: number; rechargeRatePerHour: number }> {
    const character = await this.characterRepository.findOne({
      where: { userId: user.id },
    });

    if (!character) {
      throw new NotFoundException('Aucun personnage trouvé pour ce joueur');
    }

    return {
      enduranceCurrent: this.calculateEndurance(character),
      enduranceMax: character.enduranceMax,
      rechargeRatePerHour: 60 / ENDURANCE_REGEN_MINUTES,
    };
  }
}
