package com.banesco.module.service_order_payment_search.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.instruction.domain.model.Instruction;
import com.banesco.module.service_order_payment_search.application.usecase.ServiceOrderPaymentSearchUseCase;
import com.banesco.module.service_order_payment_search.domain.dto.request.ServiceOrderPaymentSearchRequest;
import com.banesco.module.service_order_payment_search.domain.dto.response.ServiceOrderPaymentSearchResponse;
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("/service-order-payment-search")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ServiceOrderPaymentSearchResource {

    private final ServiceOrderPaymentSearchUseCase useCase;

    @Inject
    public ServiceOrderPaymentSearchResource(
        ServiceOrderPaymentSearchUseCase useCase
    ) {
        this.useCase = useCase;
    }

    @GET
    @Path("/retrieve/{partyReferenceId}/{channelCode}")
    @Operation(
        summary = "Recuperar informacion de la transaccion",
        description = "Consulta de una trasanccion de pago por id de archivo"
    )
    @APIResponses(value = {
        @APIResponse(
            responseCode = "200",
            description = "Operacion exitosa",
            content = @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(
                    implementation = ApiResponse.class,
                    properties = {
                        @SchemaProperty(
                            name = "data",
                            oneOf = {ServiceOrderPaymentSearchResponse.class}
                        ),
                        @SchemaProperty(
                            name = "statusResponse",
                            implementation = StatusResponse.class
                        )
                    }
                ),
                examples = {
                    @ExampleObject(
                        name = "Ejemplo exitoso (BOLE)",
                        value = """
                        {
                          "data": {
                            "servicingOrderProcedure": [
                                {
                                    "document": {
                                        "documentName": "TESTING.CSV"
                                    },
                                    "transaction": {
                                        "transactionIdentification": {
                                            "identifierValue": "2"
                                        },
                                        "transactionStatus": {
                                            "statusType": "PENDING",
                                            "statusName": "PENDIENTE",
                                            "statusAccepted": 0,
                                            "statusRejected": 0,
                                            "statusExpired": 2
                                        },
                                        "transactionDate": [
                                            {
                                                "dateType": "EXECUTED_DATE",
                                                "date": "2026-01-05 14:35:45.0372395"
                                            }
                                        ],
                                        "transactionDetails": {
                                            "transactionQuantity": 1000
                                        }
                                    }
                                },
                                {
                                    "document": {
                                        "documentName": "TESTING.CSV"
                                    },
                                    "transaction": {
                                        "transactionIdentification": {
                                            "identifierValue": "3"
                                        },
                                        "transactionStatus": {
                                            "statusType": "IN_PROGRESS",
                                            "statusName": "EN CURSO",
                                            "statusAccepted": 0,
                                            "statusRejected": 0,
                                            "statusExpired": 5
                                        },
                                        "transactionDate": [
                                            {
                                                "dateType": "EXECUTED_DATE",
                                                "date": "2026-01-05 14:39:52.3840159"
                                            }
                                        ],
                                        "transactionDetails": {
                                            "transactionQuantity": 1000
                                        }
                                    }
                                }
                            ]
                          },
                          "statusResponse": {
                            "statusCode": "200",
                            "message": "Operacion exitosa"
                          }
                        }
                        """
                    ),
                    @ExampleObject(
                            name = "Ejemplo exitoso (BOL)",
                            value = """
                            {
                              "data": {
                                "servicingOrderProcedure": [
                                    {
                                        "transaction": {
                                            "transactionIdentification": {
                                                "identifierValue": "1"
                                            },
                                            "transactionStatus": {
                                                "statusType": "APPROVED",
                                                "statusName": "Aprobada"
                                            },
                                            "transactionDate": [
                                                {
                                                    "dateType": "INITIATED_DATE",
                                                    "date": "2024-06-15T10:30:00Z"
                                                }
                                            ],
                                            "transactionInvolvement": [
                                                {
                                                    "partyReference": {
                                                        "partyIdentification": [
                                                            {
                                                                "partyIdentification": {
                                                                    "identifierValue": "V20132859"
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ],
                                            "financialTransaction": {
                                                "amount": 150.75,
                                                "currencyCode": "VES"
                                            },
                                            "name": "Enviada",
                                            "description": "cobro a pepito"
                                        }
                                    },
                                    {
                                        "transaction": {
                                            "transactionIdentification": {
                                                "identifierValue": "2"
                                            },
                                            "transactionStatus": {
                                                "statusType": "PENDING",
                                                "statusName": "Pendiente"
                                            },
                                            "transactionDate": [
                                                {
                                                    "dateType": "INITIATED_DATE",
                                                    "date": "2024-06-16T14:49:00Z"
                                                }
                                            ],
                                            "transactionInvolvement": [
                                                {
                                                    "partyReference": {
                                                        "partyIdentification": [
                                                            {
                                                                "partyIdentification": {
                                                                    "identifierValue": "V20132859"
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ],
                                            "financialTransaction": {
                                                "amount": 350.0,
                                                "currencyCode": "VES"
                                            },
                                            "name": "Recibida",
                                            "description": "pago a proveedor"
                                        }
                                    },
                                    {
                                        "transaction": {
                                            "transactionIdentification": {
                                                "identifierValue": "3"
                                            },
                                            "transactionStatus": {
                                                "statusType": "REJECTED",
                                                "statusName": "Rechazado"
                                            },
                                            "transactionDate": [
                                                {
                                                    "dateType": "INITIATED_DATE",
                                                    "date": "2024-06-17T09:15:00Z"
                                                }
                                            ],
                                            "transactionInvolvement": [
                                                {
                                                    "partyReference": {
                                                        "partyIdentification": [
                                                            {
                                                                "partyIdentification": {
                                                                    "identifierValue": "V20132859"
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ],
                                            "financialTransaction": {
                                                "amount": 200.0,
                                                "currencyCode": "VES"
                                            },
                                            "name": "Enviada",
                                            "description": "cobro a cliente"
                                        }
                                    },
                                    {
                                        "transaction": {
                                            "transactionIdentification": {
                                                "identifierValue": "4"
                                            },
                                            "transactionStatus": {
                                                "statusType": "APPROVED",
                                                "statusName": "Aprobada"
                                            },
                                            "transactionDate": [
                                                {
                                                    "dateType": "INITIATED_DATE",
                                                    "date": "2024-06-18T11:20:00Z"
                                                }
                                            ],
                                            "transactionInvolvement": [
                                                {
                                                    "partyReference": {
                                                        "partyIdentification": [
                                                            {
                                                                "partyIdentification": {
                                                                    "identifierValue": "V20132859"
                                                                }
                                                            }
                                                        ]
                                                    }
                                                }
                                            ],
                                            "financialTransaction": {
                                                "amount": 750.0,
                                                "currencyCode": "VES"
                                            },
                                            "name": "Recibida",
                                            "description": "pago a proveedor"
                                        }
                                    }
                                ]
                              },
                              "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 = {ServiceOrderPaymentSearchResponse.class}
                        ),
                        @SchemaProperty(
                            name = "statusResponse",
                            implementation = StatusResponse.class
                        )
                    }
                ),
                examples = {
                    @ExampleObject(
                        name = "Error VDE01 - Campo obligatorio",
                        value = """
                        {
                          "data": null,
                          "statusResponse": {
                            "statusCode": "VDE01",
                            "message": "El campo partyReferenceId 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 channelCode. Valores permitidos: BOL, BOLE"
                          }
                        }
                        """
                    )
                }
            )
        ),
        @APIResponse(
            responseCode = "401",
            description = "No autorizado",
            content = @Content(
                mediaType = MediaType.APPLICATION_JSON,
                schema = @Schema(
                    implementation = ApiResponse.class,
                    properties = {
                        @SchemaProperty(
                            name = "data",
                            oneOf = {ServiceOrderPaymentSearchResponse.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 = {ServiceOrderPaymentSearchResponse.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("partyReferenceId")
        @Parameter(description = "Identificacion del cliente", required = true, example = "J012341234")
        String partyReferenceId,

        @PathParam("channelCode")
        @Parameter(description = "Codigo del canal (BOL, BOLE)", required = true, example = "BOLE")
        String channelCode,

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

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

        @QueryParam("initiatedDate")
        @Parameter(description = "Fecha de creación", example = "2024-06-15T10:30:00Z")
        String initiatedDate,

        @QueryParam("instructionRequestId")
        @Parameter(description = "ID de la peticion de pago", example = "2")
        String instructionRequestId,

        @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 instruccion de archivo id: {}", partyReferenceId);

        return useCase.execute(
            ServiceOrderPaymentSearchRequest.builder()
                .customerReferenceFintechId(Objects.toString(customerReferenceFintechId, ""))
                .appId(Objects.toString(appId, ""))
                .procedureRequest(Instruction.fromResource(
                    partyReferenceId,
                    initiatedDate,
                    instructionRequestId,
                    channelCode
                ))
                .device(
                    Device.builder()
                        .deviceType(deviceType)
                        .deviceDescription(deviceDescription)
                        .deviceIp(deviceIp)
                        .deviceSessionReference(deviceSessionReference)
                        .build()
                )
                .build()
        );
    }
}