package com.banesco.module.legal_customer_product_directory.infrastructure.resource;

import com.banesco.common.domain.model.ApiResponse;
import com.banesco.common.domain.model.Device;
import com.banesco.common.domain.model.StatusResponse;
import com.banesco.module.legal_customer_product_directory.application.usecase.LegalCustomerProductDirectoryUseCase;
import com.banesco.module.legal_customer_product_directory.domain.dto.request.LegalCustomerProductDirectoryRequest;
import com.banesco.module.legal_customer_product_directory.domain.dto.response.LegalCustomerProductDirectoryResponse;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.ExampleObject;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.media.SchemaProperty;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;

import java.util.Objects;

@Slf4j
@Path("/legal-customer-product-directory")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class LegalCustomerProductDirectoryResource {

    private final LegalCustomerProductDirectoryUseCase useCase;

    @Inject
    public LegalCustomerProductDirectoryResource(
        LegalCustomerProductDirectoryUseCase useCase
    ) {
        this.useCase = useCase;
    }

    @GET
    @Path("/retrieve/{customerId : (?!retrieve$).*}")
    @Operation(
        summary = "Recuperar productos de cliente legal",
        description = "Consulta masiva de cuentas por numero de cliente "
    )
    @APIResponses(value = {
        @APIResponse(
            responseCode = "200",
            description = "Operacion exitosa",
            content = @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(
                    implementation = ApiResponse.class,
                    properties = {
                        @SchemaProperty(
                            name = "data",
                            oneOf = {LegalCustomerProductDirectoryResponse.class}
                        ),
                        @SchemaProperty(
                            name = "statusResponse",
                            implementation = StatusResponse.class
                        )
                    }
                ),
                examples = @ExampleObject(
                    name = "Ejemplo exitoso",
                    value = """
                    {
                      "data": {
                        "customerProductAndServiceDirectory": {
                          "accounts": [
                            {
                              "accountStatus": {
                                "status": "A",
                                "statusType": "ENABLED"
                              },
                              "accountType": "CURRENT_ACCOUNT",
                              "accountIdentification": [
                                {
                                  "accountIdentificationType": "ACCOUNT_NUMBER",
                                  "accountIdentification": {
                                    "identifierValue": "01340025330253093528"
                                  }
                                },
                                {
                                  "accountIdentificationType": "BANK_NUMBER",
                                  "accountIdentification": {
                                    "identifierValue": "01"
                                  }
                                },
                                {
                                  "accountIdentificationType": "PRODUCT_CODE",
                                  "accountIdentification": {
                                    "identifierValue": "3980"
                                  }
                                },
                                {
                                  "accountIdentificationType": "ACCOUNT_CLASS",
                                  "accountIdentification": {
                                    "identifierValue": "80"
                                  }
                                }
                              ],
                              "accountBalance": [
                                {
                                  "balanceAmount": 390417.36,
                                  "balanceType": "AVAILABLE_BALANCE"
                                },
                                {
                                  "balanceAmount": 100000.00,
                                  "balanceType": "DAILY_MAXIMUM"
                                },
                                {
                                  "balanceAmount": 3000000.00,
                                  "balanceType": "MONTHLY_MAXIMUM"
                                },
                                {
                                  "balanceAmount": 0.01,
                                  "balanceType": "TRANSACTION_MINIMUM"
                                },
                                {
                                  "balanceAmount": 100000.00,
                                  "balanceType": "TRANSACTION_MAXIMUM"
                                }
                              ],
                              "accountCurrency": [
                                {
                                  "currencyCode": "BS",
                                  "currencyType": "BASE"
                                }
                              ],
                              "accountInvolvement": [
                                {
                                  "accountInvolvementType": "PARTY_IS_OWNER_OF_ACCOUNT",
                                  "partyReference": {
                                    "partyName": [
                                      {
                                        "fullName": "TASCA RESTAURANT GOOD WORLD CEN, C.A."
                                      }
                                    ],
                                    "partyType": "ORGANIZATION",
                                    "partyIdentification": [
                                      {
                                        "partyIdentificationType": "TAX_IDENTIFICATION_NUMBER",
                                        "partyIdentification": {
                                          "identifierValue": "J000000001"
                                        }
                                      },
                                      {
                                        "partyIdentificationType": "TELEPHONE_NUMBER",
                                        "partyIdentification": {
                                          "identifierValue": "04122710660"
                                        }
                                      },
                                      {
                                        "partyIdentificationType": "TELEPHONE_OPERATOR",
                                        "partyIdentification": {
                                          "identifierValue": "0412"
                                        }
                                      }
                                    ]
                                  }
                                }
                              ],
                              "accountRelationship": [
                                {
                                  "accountRelationshipType": "ACCOUNT_IS_SUB_ACCOUNT_FOR_ACCOUNT"
                                }
                              ],
                              "agreement": [
                                {
                                  "arrangement": [
                                    {
                                      "arrangementType": "INTEREST_ARRANGEMENT"
                                    }
                                  ]
                                }
                              ]
                            }
                          ]
                        }
                      },
                      "statusResponse": {
                        "statusCode": "200",
                        "message": "Operacion exitosa"
                      }
                    }
                    """
                )
            )
        ),
        @APIResponse(
            responseCode = "400",
            description = "Error en formato o campo requerido",
            content = @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(
                    implementation = ApiResponse.class,
                    properties = {
                        @SchemaProperty(
                            name = "data",
                            oneOf = {LegalCustomerProductDirectoryResponse.class}
                        ),
                        @SchemaProperty(
                            name = "statusResponse",
                            implementation = StatusResponse.class
                        )
                    }
                ),
                examples = {
                    @ExampleObject(
                        name = "Error VDE01 - Campo obligatorio",
                        value = """
                        {
                          "data": null,
                          "statusResponse": {
                            "statusCode": "VDE01",
                            "message": "El campo customerId es obligatorio"
                          }
                        }
                        """
                    ),
                    @ExampleObject(
                        name = "Error VDE02 - Valor no permitido",
                        value = """
                        {
                          "data": null,
                          "statusResponse": {
                            "statusCode": "VDE02",
                            "message": "El valor 'XYZ' no es permitido para el campo accountStatus. Valores permitidos: A, O, ACTBSUSD"
                          }
                        }
                        """
                    )
                }
            )
        ),
        @APIResponse(
            responseCode = "401",
            description = "No autorizado",
            content = @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(
                    implementation = ApiResponse.class,
                    properties = {
                        @SchemaProperty(
                            name = "data",
                            oneOf = {LegalCustomerProductDirectoryResponse.class}
                        ),
                        @SchemaProperty(
                            name = "statusResponse",
                            implementation = StatusResponse.class
                        )
                    }
                ),
                examples = {
                    @ExampleObject(
                        name = "Error VRN08 - Identificacion del fintechId no coincide",
                        value = """
                        {
                          "data": null,
                          "statusResponse": {
                            "statusCode": "VRN08",
                            "message": "El fintechId proporcionado no coincide con el registrado para este cliente"
                          }
                        }
                        """
                    )
                }
            )
        ),
        @APIResponse(
            responseCode = "503",
            description = "Servicio no disponible",
            content = @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(
                    implementation = ApiResponse.class,
                    properties = {
                        @SchemaProperty(
                            name = "data",
                            oneOf = {LegalCustomerProductDirectoryResponse.class}
                        ),
                        @SchemaProperty(
                            name = "statusResponse",
                            implementation = StatusResponse.class
                        )
                    }
                ),
                examples = {
                    @ExampleObject(
                        name = "Error VRN04 - Fuera de horario",
                        value = """
                        {
                          "data": null,
                          "statusResponse": {
                            "statusCode": "VRN04",
                            "message": "El servicio no esta disponible fuera del horario operativo"
                          }
                        }
                        """
                    ),
                    @ExampleObject(
                        name = "Error VDR13 - OSB no disponible",
                        value = """
                        {
                          "data": null,
                          "statusResponse": {
                            "statusCode": "VDR13",
                            "message": "El servicio OSB no esta disponible en este momento"
                          }
                        }
                        """
                    )
                }
            )
        )
    })
    public Response retrieve(
        @PathParam("customerId")
        @Parameter(description = "Numero de cliente  (VCUSCUN)", example = "200053197")
        String customerId,

        @QueryParam("customerReferenceFintechId")
        @Parameter(description = "ID de la fintech", example = "pranical-test")
        String customerReferenceFintechId,

        @QueryParam("appId")
        @Parameter(description = "ID de la aplicacion", example = "DANIAPP")
        String appId,

        @QueryParam("bankNumber")
        @Parameter(description = "Numero de banco (VACMBNK)", example = "01")
        String bankNumber,

        @QueryParam("currencyCode")
        @Parameter(description = "Codigo de moneda (VACMCCY)", example = "BS")
        String currencyCode,

        @QueryParam("accountStatus")
        @Parameter(description = "Estatus de cuenta (VACMAST). 'A'=Activada, 'D'=Desactivada, 'ACTBSUSD'=Ambas", example = "A")
        String accountStatus,

        @QueryParam("productCvCode")
        @Parameter(description = "Codigo de Producto Cuenta Verde (VACMPROCV). 'CV'=Cuenta verde, 'CVFL'=Cuenta verde con opcion activa", example = "CV")
        String productCvCode,

        @QueryParam("productCode")
        @Parameter(description = "Codigo de producto (VACMPRO)", example = "3980")
        String productCode,

        @QueryParam("channelCode")
        @Parameter(description = "Codigo de canal (VAFILICANAL)", example = "APP")
        String channelCode,

        @QueryParam("serviceType")
        @Parameter(description = "Tipo de servicio (VAFILICOSER)", example = "P2P")
        String serviceType,

        @QueryParam("affiliationStatus")
        @Parameter(description = "Estatus de afiliacion (VAFILISTATU)", example = "A")
        String affiliationStatus,

        @QueryParam("limitType")
        @Parameter(description = "Pagador/Receptor (VALIMIT). 'PAG'=Pagadora, 'REC'=Receptora", example = "PAG")
        String limitType,

        @QueryParam("casheaIndicator")
        @Parameter(description = "Indicador cash (VCASHEA). 'SI'=En tabla cashea, 'NO'=No en tabla cashea", example = "SI")
        String casheaIndicator,

        @QueryParam("deviceType")
        @Parameter(description = "Tipo de dispositivo", example = "Mobile")
        String deviceType,

        @QueryParam("deviceDescription")
        @Parameter(description = "Descripcion del dispositivo", example = "Xiaomi Note 11 PRO")
        String deviceDescription,

        @QueryParam("deviceIp")
        @Parameter(description = "Direccion IP del dispositivo", example = "127.0.0.1")
        String deviceIp,

        @QueryParam("deviceSessionReference")
        @Parameter(description = "Referencia de la peticion del dispositivo", example = "12345678901304")
        String deviceSessionReference
    ) {
        log.info("Iniciando consulta para cliente : {}", customerId);

        return useCase.execute(
            LegalCustomerProductDirectoryRequest.builder()
                .customerId(Objects.toString(customerId, ""))
                .customerReferenceFintechId(Objects.toString(customerReferenceFintechId, ""))
                .appId(Objects.toString(appId, ""))
                .bankNumber(Objects.toString(bankNumber, ""))
                .currencyCode(Objects.toString(currencyCode, ""))
                .accountStatus(Objects.toString(accountStatus, ""))
                .productCvCode(Objects.toString(productCvCode, ""))
                .productCode(Objects.toString(productCode, ""))
                .channelCode(Objects.toString(channelCode, ""))
                .serviceType(Objects.toString(serviceType, ""))
                .affiliationStatus(Objects.toString(affiliationStatus, ""))
                .limitType(Objects.toString(limitType, ""))
                .casheaIndicator(Objects.toString(casheaIndicator, ""))
                .device(
                    Device.builder()
                        .deviceType(deviceType)
                        .deviceDescription(deviceDescription)
                        .deviceIp(deviceIp)
                        .deviceSessionReference(deviceSessionReference)
                        .build()
                )
                .build()
        );
    }
}