import { NotFoundError } from '../../../domain/errors/not-found-error';
import { ITokenRepository } from '../../../domain/repositories/token-repository';
import { CoinMarketCapClient } from '../../../infrastructure/external/coinmarketcap-client';

export interface TokenChartPoint {
  readonly timestamp: string;
  readonly price: number;
}

export interface GetTokenChartInput {
  readonly tokenId: string;
  readonly timeframe: string;
}

const TIMEFRAME_CONFIG: Record<string, { interval: string; count: number }> = {
  LIVE: { interval: '5m', count: 24 },
  '1m': { interval: '5m', count: 12 },
  '1H': { interval: '5m', count: 12 },
  '1D': { interval: 'hourly', count: 24 },
  '1W': { interval: 'daily', count: 7 },
  '1M': { interval: 'daily', count: 30 },
};

export class GetTokenChartUseCase {
  constructor(
    private readonly tokenRepository: ITokenRepository,
    private readonly coinMarketCapClient: CoinMarketCapClient,
  ) {}

  async execute(input: GetTokenChartInput): Promise<TokenChartPoint[]> {
    const token = await this.tokenRepository.findById(input.tokenId);
    if (!token) {
      throw new NotFoundError('Token', input.tokenId);
    }

    const config = TIMEFRAME_CONFIG[input.timeframe] ?? { interval: 'daily', count: 7 };
    const cmcId = await this.coinMarketCapClient.getCoinIdByToken(
      token.name,
      token.symbol,
      token.isNative,
    );

    if (!cmcId) {
      return this.generateFallbackChart(config.count);
    }

    return this.coinMarketCapClient.getPriceHistory(cmcId, config.interval, config.count);
  }

  private generateFallbackChart(count: number): TokenChartPoint[] {
    const now = Date.now();
    const intervalMs = 24 * 60 * 60_000 / Math.max(count, 1);
    const points: TokenChartPoint[] = [];

    for (let i = count - 1; i >= 0; i--) {
      const timestamp = new Date(now - i * intervalMs).toISOString();
      const price = Math.random() * 100;
      points.push({ timestamp, price });
    }

    return points;
  }
}
