"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UpdateTokenUseCase = void 0;
const token_1 = require("../../../domain/entities/token");
const not_found_error_1 = require("../../../domain/errors/not-found-error");
const validation_error_1 = require("../../../domain/errors/validation-error");
class UpdateTokenUseCase {
    tokenRepository;
    networkRepository;
    imageStorage;
    coinMarketCapClient;
    logger;
    constructor(tokenRepository, networkRepository, imageStorage, coinMarketCapClient, logger) {
        this.tokenRepository = tokenRepository;
        this.networkRepository = networkRepository;
        this.imageStorage = imageStorage;
        this.coinMarketCapClient = coinMarketCapClient;
        this.logger = logger;
    }
    async execute(tokenId, input) {
        const existing = await this.tokenRepository.findById(tokenId);
        if (!existing) {
            throw new not_found_error_1.NotFoundError('Token', tokenId);
        }
        const networkId = input.networkId ?? existing.networkId;
        const network = await this.networkRepository.findById(networkId);
        if (!network) {
            throw new not_found_error_1.NotFoundError('Network', networkId);
        }
        const isNative = input.isNative ?? existing.isNative;
        const address = input.address !== undefined ? input.address : existing.address;
        if (!isNative && !address) {
            throw new validation_error_1.ValidationError('Non-native tokens must have a contract address', {
                address: ['Contract address is required'],
            });
        }
        const name = input.name ?? existing.name;
        const symbol = input.symbol ?? existing.symbol;
        const code = input.code ?? existing.code;
        let thumbnail = existing.thumbnail;
        if (input.thumbnail !== undefined && input.thumbnail !== existing.thumbnail) {
            thumbnail = input.thumbnail
                ? await this.imageStorage.downloadAndStore('token', existing.id, input.thumbnail, {
                    name,
                    symbol,
                })
                : null;
        }
        const info = await this.resolveTokenInfo(existing.info, input, { name, symbol, code });
        const updated = new token_1.Token(existing.id, isNative, isNative ? null : address, networkId, thumbnail, name, symbol, input.decimals ?? existing.decimals, code, info, input.isActive ?? existing.isActive, input.minimumSwapValue !== undefined ? input.minimumSwapValue : existing.minimumSwapValue, existing.mcap, existing.createdAt, new Date());
        return this.tokenRepository.update(updated);
    }
    async resolveTokenInfo(existingInfo, input, token) {
        if (input.info !== undefined) {
            return input.info;
        }
        if (input.cmcId === undefined && input.code === undefined) {
            return existingInfo;
        }
        try {
            const coin = input.cmcId
                ? await this.coinMarketCapClient.getCoin(input.cmcId)
                : await this.coinMarketCapClient.getCoinInfoBySlug(token.code);
            if (coin?.description) {
                return coin.description;
            }
        }
        catch (error) {
            this.logger.warn('Failed to fetch token info from CoinMarketCap, using fallback', {
                code: token.code,
                cmcId: input.cmcId,
                error,
            });
        }
        return existingInfo;
    }
}
exports.UpdateTokenUseCase = UpdateTokenUseCase;
//# sourceMappingURL=update-token.use-case.js.map