package kz.arta.nca_iiscon.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import kz.arta.nca_iiscon.data.forward.ForwardApplication;
import kz.arta.nca_iiscon.data.search.SearchOrderByReferenceNumberRequest;
import kz.arta.nca_iiscon.data.search.SearchOrderRequestWrapper;
import kz.arta.nca_iiscon.service.ForwardApplicationNcaService;
import kz.arta.nca_iiscon.service.NcaIISConService;
import kz.arta.nca_iiscon.util.XmlToJsonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.IIOImage;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Base64;

@Slf4j
@ResponseBody
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/service/nca")
public class NcaIISConController {

    private final NcaIISConService service;

    private final ForwardApplicationNcaService forwardService;

    private final ObjectMapper objectMapper = new ObjectMapper();

    @PostMapping(value = "/iiscon", produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Object getSearchOrderByReferenceNumber(@RequestPart(value = "data") String dataJson,
                                                                @RequestPart(value = "file", required = false) MultipartFile file
    ) throws Exception {
        SearchOrderRequestWrapper wrapper = objectMapper.readValue(dataJson, SearchOrderRequestWrapper.class);

        SearchOrderByReferenceNumberRequest request = wrapper.getRequest();
        String savedPhoto = wrapper.getSavedPhoto();
        String applicantNumber = wrapper.getApplicantNumber();

        log.info("Received request with referenceNumber: {}", request.getReferenceNumber());
        // Отправляем запрос и получаем ответ
        Object response = service.sendRequestByTemplate(request);
        log.info("SHEP Response {}", response);

        String base64photo;
        if (savedPhoto != null && !savedPhoto.isEmpty()) {
            // Опция 1: base64 строка из JSON
            if (savedPhoto.contains(",")) {
                base64photo = savedPhoto.substring(savedPhoto.indexOf(",") + 1);
            } else {
                base64photo = savedPhoto;
            }
        } else if (file != null && !file.isEmpty()) {
            // Опция 2: загруженный файл - конвертируем в JPEG и кодируем в base64
            base64photo = convertImageToJpegBase64(file);
        } else {
            throw new IllegalArgumentException("Нет данных для фото: укажите savedPhoto (base64) или загрузите file");
        }
        return XmlToJsonUtil.extractDataAsJson(response, true, base64photo, applicantNumber);
    }

    @PostMapping(value = "/forward", produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Object getInfoOneC(
            @RequestBody ForwardApplication request
    ) throws Exception {

        // Отправляем запрос и получаем ответ
        Object response = forwardService.sendRequestByTemplate(request);

        // Извлекаем data и конвертируем в JSON
        String jsonResponse = XmlToJsonUtil.extractDataAsJson(response, false, null, null);

        log.info("Converted response to JSON");

        return jsonResponse;
    }

    //    /**
//     * Конвертирует загруженный файл (любого формата) в JPEG и возвращает base64 строку
//     */
    private String convertImageToJpegBase64(MultipartFile file) throws Exception {
        byte[] fileBytes = file.getBytes();
        String contentType = file.getContentType();
        String originalFilename = file.getOriginalFilename();

        log.info("Processing file: {}, contentType: {}", originalFilename, contentType);

        // Если файл уже в формате JPEG, просто кодируем в base64 без конвертации
        if (contentType != null && (contentType.equals("image/jpeg") || contentType.equals("image/jpg"))) {
            log.info("File is already JPEG, encoding without conversion");
            return Base64.getEncoder().encodeToString(fileBytes);
        }

        try {
            BufferedImage image = ImageIO.read(new ByteArrayInputStream(fileBytes));

            if (image == null) {
                log.warn("ImageIO could not read the image format. Returning raw base64. File may not be in JPEG format.");
                return Base64.getEncoder().encodeToString(fileBytes);
            }

            // Изменяем размер изображения до 360x480 (сохраняя пропорции)
            BufferedImage resizedImage = resizeImage(image, 360, 480);

            BufferedImage jpegImage;
            if (resizedImage.getType() == BufferedImage.TYPE_4BYTE_ABGR ||
                    resizedImage.getType() == BufferedImage.TYPE_INT_ARGB) {
                jpegImage = new BufferedImage(resizedImage.getWidth(), resizedImage.getHeight(), BufferedImage.TYPE_INT_RGB);
                jpegImage.createGraphics().drawImage(resizedImage, 0, 0, java.awt.Color.WHITE, null);
            } else {
                jpegImage = resizedImage;
            }

            // Конвертируем в JPEG с сжатием
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageWriter jpegWriter = ImageIO.getImageWritersByFormatName("jpg").next();
            ImageWriteParam jpegParams = jpegWriter.getDefaultWriteParam();
            jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            jpegParams.setCompressionQuality(0.75f);

            jpegWriter.setOutput(ImageIO.createImageOutputStream(outputStream));
            jpegWriter.write(null, new IIOImage(jpegImage, null, null), jpegParams);
            jpegWriter.dispose();

            // Кодируем в base64
            byte[] jpegBytes = outputStream.toByteArray();
            return Base64.getEncoder().encodeToString(jpegBytes);

        } catch (Exception e) {
            log.error("Error converting image to JPEG: {}. Returning raw base64.", e.getMessage());
            return Base64.getEncoder().encodeToString(fileBytes);
        }
    }

    /**
     * Изменяет размер изображения, сохраняя пропорции, чтобы уместиться в заданные максимальные размеры
     */
    private BufferedImage resizeImage(BufferedImage originalImage, int maxWidth, int maxHeight) {
        int originalWidth = originalImage.getWidth();
        int originalHeight = originalImage.getHeight();

        // Вычисляем новые размеры, сохраняя пропорции
        double widthRatio = (double) maxWidth / originalWidth;
        double heightRatio = (double) maxHeight / originalHeight;
        double ratio = Math.min(widthRatio, heightRatio);

        int newWidth = (int) (originalWidth * ratio);
        int newHeight = (int) (originalHeight * ratio);

        // Если изображение уже меньше максимальных размеров, возвращаем оригинал
        if (ratio >= 1.0) {
            return originalImage;
        }

        // Создаем новое изображение с уменьшенными размерами
        BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = resizedImage.createGraphics();

        // Настраиваем качество ресайза
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        g.drawImage(originalImage, 0, 0, newWidth, newHeight, null);
        g.dispose();

        return resizedImage;
    }
}