import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { PlayerAssets, PlayerAssetType } from './player_assets.entity';

@Injectable()
export class PlayerAssetsService {
  constructor(
    @InjectRepository(PlayerAssets)
    private readonly playerAssetsRepository: Repository<PlayerAssets>,
  ) {}

  async grantAsset(userId: bigint, assetType: PlayerAssetType, assetId: string, source = 'system', metadata?: Record<string, unknown>): Promise<PlayerAssets> {
    const normalizedAssetId = this.normalizeAssetId(assetId);
    const existing = await this.playerAssetsRepository.findOne({
      where: { user_id: userId, asset_type: assetType, asset_id: normalizedAssetId },
    });
    if (existing) {
      return existing;
    }

    const row = new PlayerAssets();
    row.user_id = userId;
    row.asset_type = assetType;
    row.asset_id = normalizedAssetId;
    row.source = source || 'system';
    row.metadata = metadata ?? null;
    row.acquired_at = new Date();
    return await this.playerAssetsRepository.save(row);
  }

  async hasAsset(userId: bigint, assetType: PlayerAssetType, assetId: string): Promise<boolean> {
    const normalizedAssetId = (assetId || '').trim();
    if (!normalizedAssetId) {
      return false;
    }
    const count = await this.playerAssetsRepository.count({
      where: { user_id: userId, asset_type: assetType, asset_id: normalizedAssetId },
    });
    return count > 0;
  }

  async listAssets(userId: bigint, assetType?: PlayerAssetType): Promise<PlayerAssets[]> {
    return await this.playerAssetsRepository.find({
      where: assetType ? { user_id: userId, asset_type: assetType } : { user_id: userId },
      order: { acquired_at: 'ASC', id: 'ASC' },
    });
  }

  async listAssetIds(userId: bigint, assetType: PlayerAssetType): Promise<string[]> {
    const rows = await this.listAssets(userId, assetType);
    return rows.map((row) => row.asset_id);
  }

  async hasAssetFromSource(userId: bigint, assetType: PlayerAssetType, source: string): Promise<boolean> {
    const normalizedSource = (source || '').trim();
    if (!normalizedSource) {
      return false;
    }
    const count = await this.playerAssetsRepository.count({
      where: { user_id: userId, asset_type: assetType, source: normalizedSource },
    });
    return count > 0;
  }

  private normalizeAssetId(assetId: string): string {
    const normalized = (assetId || '').trim();
    if (!/^[A-Za-z0-9_:-]{1,100}$/.test(normalized)) {
      throw new BadRequestException('资产ID格式不正确');
    }
    return normalized;
  }
}
