package application.usecase;

import application.exception.GatewayServiceException;
import application.port.input.ICustomerProduct;
import application.port.input.command.CustomerAccountCommand;
import application.service.AccountService;
import com.banesco.common.infraestructure.helpers.LoggerHelper;
import domain.entity.AppConfiguration;
import domain.model.AccountClientContext;
import domain.model.BankingProduct;
import domain.repository.ICustomerProductPort;
import infrastructure.mapper.BankingProductMapper;
import infrastructure.mapper.CacheMapper;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.util.List;

@Slf4j
@ApplicationScoped
public class CustomerProductUseCase implements ICustomerProduct {

    private final ICustomerProductPort customerProductPort;
    private final AccountService accountService;

    @ConfigProperty(name = "app.redis.expiration")
    long cacheTtl;

    @Inject
    public CustomerProductUseCase(
            ICustomerProductPort customerProductPort,
            AccountService accountService
    ) {
        this.customerProductPort = customerProductPort;
        this.accountService = accountService;
    }

    @Override
    public List<BankingProduct> execute(CustomerAccountCommand command, AccountClientContext context, AppConfiguration appConfig, String otp, Boolean isCacheable, String requestId) {
        log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Iniciando caso de uso: api-get-db2-accounts-client-v2"));
        try {

            var customerAccountsFromService = customerProductPort.execute(command, requestId);

            // Si el servicio no devuelve nada, no hay nada que guardar ni devolver.
            if (customerAccountsFromService == null || customerAccountsFromService.isEmpty()) {
                log.info(LoggerHelper.buildInfoPrivateRequest(requestId, "El servicio principal no devolvio cuentas para requestId {}", requestId));
                return List.of();
            }

            var bankingProducts = BankingProductMapper.fromCustomerAccountList(customerAccountsFromService, appConfig.isEncryptionData());

            if(isCacheable) {
                var accountsToCache = CacheMapper.toUserAccountRedisList(
                        customerAccountsFromService,
                        context.getRedisKey(),
                        context.getFinalCustomerId(),
                        otp
                );

                log.info(LoggerHelper.buildInfoPrivateRequest(
                        requestId, String.format("Guardando %s cuentas en cache", accountsToCache.size())
                ));

                accountService.saveAccounts(
                        requestId,
                        context.getFinalCustomerId(),
                        context.getRedisKey(),
                        accountsToCache,
                        cacheTtl
                );
            }
            return bankingProducts;
        } catch (GatewayServiceException ex) {
            log.error(LoggerHelper.buildError(requestId, "Fallo la comunicacion con el servicio de api-get-db2-accounts-client-v2"));
            throw  ex;
        } finally {
            log.debug(LoggerHelper.buildInfoPrivateRequest(requestId, "Finalizado caso de uso: api-get-db2-accounts-client-v2"));
        }
    }

}