import { Injectable, BadRequestException, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Item } from './item.entity';
import { CharacterItem } from './character-item.entity';
import { Character } from '../character/entities/character.entity';
import { User } from '../user/user.entity';

@Injectable()
export class ItemService {
  constructor(
    @InjectRepository(Item)
    private readonly itemRepository: Repository<Item>,
    @InjectRepository(CharacterItem)
    private readonly charItemRepository: Repository<CharacterItem>,
    @InjectRepository(Character)
    private readonly characterRepository: Repository<Character>,
  ) {}

  findAll() {
    return this.itemRepository.find({ order: { rarity: 'ASC', name: 'ASC' } });
  }

  async getInventory(user: User) {
    const char = await this.getCharacter(user);
    return this.charItemRepository.find({
      where: { characterId: char.id },
      order: { acquiredAt: 'DESC' },
    });
  }

  async equip(charItemId: string, user: User) {
    const char = await this.getCharacter(user);
    const charItem = await this.charItemRepository.findOne({
      where: { id: charItemId, characterId: char.id },
    });
    if (!charItem) throw new NotFoundException('Item non trouvé dans l\'inventaire');

    // Déséquiper l'item du même slot (type) si existe
    const currentEquipped = await this.charItemRepository
      .createQueryBuilder('ci')
      .leftJoinAndSelect('ci.item', 'item')
      .where('ci.characterId = :cid', { cid: char.id })
      .andWhere('ci.equipped = true')
      .andWhere('item.type = :type', { type: charItem.item.type })
      .getOne();

    if (currentEquipped) {
      currentEquipped.equipped = false;
      await this.charItemRepository.save(currentEquipped);
    }

    charItem.equipped = true;
    await this.charItemRepository.save(charItem);
    return { equipped: true, item: charItem };
  }

  async unequip(slot: 'weapon' | 'armor', user: User) {
    const char = await this.getCharacter(user);
    const charItem = await this.charItemRepository
      .createQueryBuilder('ci')
      .leftJoinAndSelect('ci.item', 'item')
      .where('ci.characterId = :cid', { cid: char.id })
      .andWhere('ci.equipped = true')
      .andWhere('item.type = :type', { type: slot })
      .getOne();

    if (!charItem) throw new NotFoundException(`Aucun ${slot} équipé`);
    charItem.equipped = false;
    await this.charItemRepository.save(charItem);
    return { unequipped: true };
  }

  // Utilisé par CombatService pour charger l'équipement actif
  async getEquippedItems(characterId: string): Promise<{ weapon: CharacterItem | null; armor: CharacterItem | null }> {
    const equipped = await this.charItemRepository
      .createQueryBuilder('ci')
      .leftJoinAndSelect('ci.item', 'item')
      .where('ci.characterId = :cid', { cid: characterId })
      .andWhere('ci.equipped = true')
      .getMany();

    return {
      weapon: equipped.find(ci => ci.item.type === 'weapon') ?? null,
      armor: equipped.find(ci => ci.item.type === 'armor') ?? null,
    };
  }

  // Utilisé par CraftService pour ajouter un item crafté
  async addItemToInventory(characterId: string, itemId: string): Promise<CharacterItem> {
    const charItem = this.charItemRepository.create({ characterId, itemId, forgeLevel: 0, equipped: false });
    return this.charItemRepository.save(charItem);
  }

  private async getCharacter(user: User): Promise<Character> {
    const char = await this.characterRepository.findOne({ where: { userId: user.id } });
    if (!char) throw new BadRequestException('Aucun personnage trouvé');
    return char;
  }
}
