package com.banesco.module.correspondence.infrastructure.mapper;

import com.banesco.common.domain.model.Identifier;
import com.banesco.module.banking_product.domain.model.BankingProduct;
import com.banesco.module.correspondence.domain.dto.request.CorrespondenceRequest;
import com.banesco.module.correspondence.domain.model.Correspondence;
import com.banesco.module.instruction.domain.model.Instruction;
import com.banesco.module.instruction.domain.model.InstructionIdentification;
import com.banesco.module.instruction.domain.model.InstructionIdentificationType;
import com.banesco.module.party.domain.model.Party;
import com.banesco.module.party.domain.model.PartyIdentification;
import com.banesco.module.security_notification.domain.dto.request.SecurityNotificationRequest;
import com.banesco.module.security_notification.domain.model.SecurityNotification;
import com.banesco.module.transaction.domain.model.*;
import io.netty.util.internal.StringUtil;

import java.util.List;

public class CorrespondenceMapper {

    private CorrespondenceMapper() {}

    public static SecurityNotificationRequest toPaymentRequest(
        CorrespondenceRequest request
    ) {
        return SecurityNotificationRequest.builder()
            .fintechId(request.getCustomerReferenceFintechId())
            .id(Long.valueOf(request.getId()))
            .channelOrigin(request.getChannelCode())
            .build();
    }

    public static List<Correspondence> toModel(List<SecurityNotification> response) {
        return response.stream().map(securityNotification ->
            Correspondence.builder()
                .instructionReference(buildInstruction(securityNotification))
                .sourceReference(securityNotification.getIdTypeAlert())
                .bankingProduct(buildBankingProduct(securityNotification))
                .customerReference(buildParty(securityNotification.getIdentityRecipient()))
                .transaction(buildTransaction(securityNotification))
                .build()
        ).toList();
    }

    private static Instruction buildInstruction(SecurityNotification response) {
        return Instruction.builder()
            .instructionIdentifier(InstructionIdentification.builder()
                .identification(Identifier.builder()
                    .identifierValue(response.getId().toString())
                    .build())
                .identificationType(mapInstructionIdentificationType())
                .build())
            .build();
    }

    private static BankingProduct buildBankingProduct(SecurityNotification response) {
        return BankingProduct.builder()
            .productType(response.getCodeTypeAlert())
            .productDescription(response.getIdDiffusion())
            .build();
    }

    private static Party buildParty(String partyIdentifier) {
        return Party.builder()
            .partyIdentification(List.of(PartyIdentification.builder()
                .partyIdentification(Identifier.builder()
                    .identifierValue(partyIdentifier)
                    .build())
                .build()))
            .build();
    }

    private static Transaction buildTransaction(SecurityNotification response) {
        return Transaction.builder()
            .financialTransaction(FinancialTransaction.builder()
                .amount(response.getAmount())
                .currencyCode(response.getCurrency())
                .build())
            .transactionStatus(buildTransactionStatus(response))
            .transactionDate(buildTransactionDateTimeList(response))
            .transactionAuthorization(buildTransactionAuthorization(response))
            .transactionDetails(TransactionDetails.builder()
                .transactionDataJson(response.getDataAlertJason())
                .transactionPage(response.getPageNumber())
                .transactionPageSize(response.getPageSize())
                .build())
            .build();
    }

    private static TransactionStatus buildTransactionStatus(SecurityNotification response) {
        return TransactionStatus.builder()
            .identification(Identifier.builder()
                .identifierValue(response.getIdStatusAlert())
                .build())
            .statusType(mapTransactionStatusType(response.getName()))
            .statusName(response.getNameStatusAlert())
            .statusDescription(response.getCodeStatusAlert())
            .statusRejectedCause(response.getReasonReject())
            .build();
    }

    private static List<TransactionDateTime> buildTransactionDateTimeList(SecurityNotification response) {
        return List.of(
            TransactionDateTime.builder()
                .dateType(TransactionDateTimeType.INITIATED_DATE)
                .date(response.getDateCreate())
                .build(),
            TransactionDateTime.builder()
                .dateType(TransactionDateTimeType.EXECUTED_DATE)
                .date(response.getDateUpdate())
                .build(),
            TransactionDateTime.builder()
                .dateType(TransactionDateTimeType.EXPIRY_DATE)
                .date(response.getDateExpired())
                .build(),
            TransactionDateTime.builder()
                .dateType(TransactionDateTimeType.EXPIRY_TIME)
                .time((!StringUtil.isNullOrEmpty(response.getTimeExpired()))
                    ? Long.valueOf(response.getTimeExpired())
                    : null
                )
                .build()
        );
    }

    private static TransactionAuthorization buildTransactionAuthorization(SecurityNotification response) {
        return TransactionAuthorization.builder()
            .identification(Identifier.builder()
                .identifierValue(response.getUuidPasskey())
                .build())
            .authorizationType(response.getTypeAuthorization())
            .build();
    }

    private static InstructionIdentificationType mapInstructionIdentificationType() {
        return InstructionIdentificationType.INSTRUCTION_NUMBER;
    }

    private static TransactionStatusType mapTransactionStatusType(String codeStatusRequest) {
        if (codeStatusRequest == null) {
            return TransactionStatusType.PENDING;
        }

        return switch (codeStatusRequest.toUpperCase()) {
            case "ACT", "ACTIVO", "ACTIVA" -> TransactionStatusType.ACTIVE;
            case "PENDIENTE" -> TransactionStatusType.PENDING;
            case "EXITO", "EXITOSA", "COMPLETADO", "FINALIZADO" -> TransactionStatusType.COMPLETED;
            case "APROBADO", "APROBADA" -> TransactionStatusType.APPROVED;
            case "CONF", "CONFIRMADO", "CONFIRMADA" -> TransactionStatusType.CONFIRMED;
            case "INICIADO" -> TransactionStatusType.INITIATED;
            case "EN_PROCESO", "PROCESANDO", "EN CURSO" -> TransactionStatusType.IN_PROGRESS;
            case "RECH", "RECHAZADO", "FALLA", "FALLIDO", "RECHAZADA", "FALLIDA" -> TransactionStatusType.REJECTED;
            case "CANCELADO" -> TransactionStatusType.CANCELLED;
            case "SUSPENDIDO" -> TransactionStatusType.SUSPENDED;
            case "NOTIFICADO" -> TransactionStatusType.NOTIFIED;
            case "CONTABILIZADO" -> TransactionStatusType.BOOKED;
            case "EJECUTADO" -> TransactionStatusType.EXECUTED;
            case "EXP", "EXPIRADO", "EXPIRADA" -> TransactionStatusType.EXPIRED;
            case "ENVIADO", "ENVIADA" -> TransactionStatusType.SENT;
            case "RECIBIDO", "RECIBIDA" -> TransactionStatusType.RECEIVED;
            case "LEIDA" -> TransactionStatusType.READ;
            case "PROG", "PROGRAMADO", "PROGRAMADA" -> TransactionStatusType.PROGRAMED;
            case "TRANSATIP" -> TransactionStatusType.ATYPICAL_TRANSACTION;
            default -> TransactionStatusType.DEFAULT;
        };
    }
}