package com.banesco.application.rest.controllers;

import com.banesco.application.helper.UpdateCardStatusRequestValidator;
import com.banesco.common.application.exception.BanBackendException;
import com.banesco.common.application.exception.BanRuntimeException;
import com.banesco.common.domain.dto.bian.device.JsonHelper;
import com.banesco.common.domain.dto.bian.device.LoggerHelper;
import com.banesco.common.domain.dto.bian.response.StatusResponse;
import com.banesco.commons.config.AppConf;
import com.banesco.commons.config.StatusCodes;
import com.banesco.domain.bian.request.BusUpdateCardStatusRequest;
import com.banesco.domain.bian.response.BusUpdateCardStatusResponse;
import com.banesco.domain.ports.inbound.UpdateCardStatusUseCase;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.info.Info;
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.parameters.RequestBody;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;

@OpenAPIDefinition(info = @Info(
        title = "bus-update-card-status",
        version = "1.0",
        description = "API Business - Cancelación de TDD")
)
@Path("/card/status/update")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Slf4j
public class UpdateCardStatusController {

    private final UpdateCardStatusRequestValidator updateCardStatusRequestValidator;
    private final UpdateCardStatusUseCase updateCardStatusUseCase;


    @Inject
    AppConf appConf;

    @Inject
    public UpdateCardStatusController(
            UpdateCardStatusRequestValidator updateCardStatusRequestValidator,
            UpdateCardStatusUseCase updateCardStatusUseCase
    ) {

        this.updateCardStatusRequestValidator = updateCardStatusRequestValidator;
        this.updateCardStatusUseCase = updateCardStatusUseCase;
    }

    @PUT
    @Operation(
            summary = "updateCardStatus",
            description = "Permite cambiar el estatus de las tarjetas de los clientes."
    )
    @RequestBody(
            description = "Datos de la solicitud para actualizar el estatus de la tarjeta",
            required = true,
            content = @Content(
                    mediaType = MediaType.APPLICATION_JSON,
                    schema = @Schema(implementation = BusUpdateCardStatusRequest.class),
                    examples = {
                            @ExampleObject(
                                    name = "Ejemplo exitoso",
                                    summary = "Petición con datos válidos",
                                    value = "{\n" +
                                            "  \"requestId\": \"Req123\",\n" +
                                            "  \"customerReferenceFintechId \": \"500634269\"\n" +
                                            "  \"customerReference\": {\n" +
                                            "    \"customerIdType\": \"J\",\n" +
                                            "    \"customerId\": \"500634269\"\n" +
                                            "  },\n" +
                                            "  \"device\": {\n" +
                                            "    \"deviceType\": \"Mobile\",\n" +
                                            "    \"deviceDescription\": \"Xiaomi Note 11 PRO\",\n" +
                                            "    \"deviceIp\": \"127.0.0.1\",\n" +
                                            "    \"deviceSessionReference\": \"12345678901304\"\n" +
                                            "  },\n" +
                                            "  \"cardReference\": {\n" +
                                            "    \"cardType\": \"DebitCard\",\n" +
                                            "    \"cardNumber\": \"6012-8862-0791-7605\",\n" +
                                            "    \"cardStatusCode\": \"52\",\n" +
                                            "    \"cardStatusAction\": \"CV\",\n" +
                                            "    \"cardStatusReason\": \"Bloqueo Temporal\"\n" +
                                            "  }\n" +
                                            "}"
                            ),
                            @ExampleObject(
                                    name = "Ejemplo Error de validación",
                                    summary = "Petición con formato inválido",
                                    value = "{\n" +
                                            "  \"requestId\": \"Req123\",\n" +
                                            "  \"customerReferenceFintechId \": \"500634269\"\n" +
                                            "  \"customerReference\": {\n" +
                                            "    \"customerIdType\": \"V\",\n" +
                                            "    \"customerId\": \"500634269\"\n" +
                                            "  },\n" +
                                            "  \"device\": {\n" +
                                            "    \"deviceType\": \"Mobile\",\n" +
                                            "    \"deviceDescription\": \"Xiaomi Note 11 PRO\",\n" +
                                            "    \"deviceIp\": \"127.0.0.1\",\n" +
                                            "    \"deviceSessionReference\": \"12345678901304\"\n" +
                                            "  },\n" +
                                            "  \"cardReference\": {\n" +
                                            "    \"cardType\": \"DebitCard\",\n" +
                                            "    \"cardNumber\": \"6012886207917605\",\n" +
                                            "    \"cardStatusCode\": \"52\",\n" +
                                            "    \"cardStatusAction\": \"CV\",\n" +
                                            "    \"cardStatusReason\": \"Bloqueo Temporal\"\n" +
                                            "  }\n" +
                                            "}"
                            )
                    }
            )
    )
    @APIResponses(value = {
            @APIResponse(
                    responseCode = "200",
                    description = "Operación exitosa",

                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON,
                            schema = @Schema(implementation = BusUpdateCardStatusResponse.class),
                            examples = @ExampleObject(
                                    name = "Ejemplo exitoso",
                                    value = "{\"statusResponse\":{\"status\":\"ok\",\"statusCode\":\"200\",\"message\":\"Operacion exitosa\",\"requestId\":\"UCSS123456789\"}}"
                            )
                    )
            ),
            @APIResponse(
                    responseCode = "400",
                    description = "Error en formato o campo requerido",
                    content = @Content(
                            mediaType = MediaType.APPLICATION_JSON,
                            schema = @Schema(implementation = BusUpdateCardStatusResponse.class),
                            examples = @ExampleObject(
                                    name = "Ejemplo Error de validación",
                                    value = "{\"statusResponse\":{\"status\":\"error\",\"statusCode\":\"VDE02\",\"message\":\"VDE02 - Error en formato del campo: cardReference.cardNumber\",\"requestId\":\"UCSS123456789\"}}"
                            )
                    )
            )
    })
    public Response updateCardStatus(
            BusUpdateCardStatusRequest request) {


        BusUpdateCardStatusResponse dataResponse = null;
        log.info("INICIO =>");
        String requestId = request.getRequestId();
        log.info(LoggerHelper.buildInfoRequest(requestId, JsonHelper.getJsonFromObject(request)));

        String backendCode = StatusCodes.INTERNAL_ERROR.getStatusCode();
        String backendDesc = StatusCodes.INTERNAL_ERROR.getStatusDesc();
        String target = null;

        try {
            // Validate Request
            updateCardStatusRequestValidator.validatedRequest(request);

            updateCardStatusUseCase.execute(request);

            backendCode = StatusCodes.SUCCESS_OPERATION.getStatusCode();
            backendDesc = StatusCodes.SUCCESS_OPERATION.getStatusDesc();
        } catch (BanRuntimeException e) {
            backendCode = e.getStatusCode().getStatusCode();

            log.error(LoggerHelper.buildError(requestId, backendCode + " - " + e.getMessage()));
            if (e.getTarget() != null) {
                backendDesc = e.getStatusCode().getStatusDesc().formatted(e.getTarget());
            } else {
                backendDesc = e.getStatusCode().getStatusDesc();
            }


        } catch (BanBackendException e) {
            backendCode = e.getBackendCode();
            log.error(LoggerHelper.buildError(requestId, backendCode + " - " + e.getMessage()));
            if (e.getTarget() != null) {
                backendDesc = e.getBackendDesc() + " - " + e.getTarget();
            } else {
                backendDesc = e.getBackendDesc();
            }

        } catch (Exception e) {
            log.error(LoggerHelper.buildError(requestId, backendCode + " - " + e.getMessage()));
        }

        BusUpdateCardStatusResponse response = new BusUpdateCardStatusResponse();
        response.setStatusResponse(
                new StatusResponse(
                        backendCode.equals(StatusCodes.SUCCESS_OPERATION.getStatusCode()) ? "ok" : "error",
                        backendCode,
                        backendDesc,
                        requestId
                )
        );

        String outputJson = response.toString();

        log.info(LoggerHelper.buildInfoResponse(requestId, outputJson));

        return Response.status(200)
                .entity(outputJson)
                .build();
    }


}
