package com.dacrt.SBIABackend.security.service;

import com.dacrt.SBIABackend.security.service.EmailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

@Service
@ConditionalOnProperty(name = "app.email.provider", havingValue = "google")
public class GoogleOAuthEmailService implements EmailService {

    private static final Logger logger = LoggerFactory.getLogger(GoogleOAuthEmailService.class);

    @Value("${google.api.email.url:https://gmail.googleapis.com/gmail/v1/users/me/messages/send}")
    private String googleApiUrl;

    @Value("${google.oauth2.client-id}")
    private String clientId;

    @Value("${google.oauth2.client-secret}")
    private String clientSecret;

    @Value("${google.oauth2.refresh-token}")
    private String refreshToken;

    @Value("${google.oauth2.token-url}")
    private String tokenUrl;

    private final RestTemplate restTemplate = new RestTemplate();

    /**
     * Método que solicita un Access Token fresco a Google utilizando el Refresh Token.
     */
    private String obtenerAccessTokenValido() {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
            map.add("client_id", clientId);
            map.add("client_secret", clientSecret);
            map.add("refresh_token", refreshToken);
            map.add("grant_type", "refresh_token");
            
            logger.info("=== TOKEN CARGADO EN SERVIDOR ===");
            logger.info("Refresh Token actual: {}", refreshToken);
            logger.info("Client ID actual: {}", clientId);
            logger.info("==================================");

            HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);

            //tokenUrl = "https://oauth2.googleapis.com/token";
            
            ResponseEntity<Map> response = restTemplate.postForEntity(tokenUrl, request, Map.class);

            if (response.getBody() != null && response.getBody().containsKey("access_token")) {
                return (String) response.getBody().get("access_token");
            } else {
                throw new RuntimeException("Respuesta de Google OAuth2 sin access_token");
            }
        } catch (Exception e) {
            logger.error("Error renovando Access Token con Google OAuth2: {}", e.getMessage(), e);
            throw new RuntimeException("No se pudo obtener el Access Token de Google", e);
        }
    }

    @Override
    public void sendEmail(String recipient, String subject, String body) {
        try {
            // 1. Obtener un Access Token fresco mediante el Refresh Token
            String accessTokenValido = obtenerAccessTokenValido();

         // 2. Codificar el Subject en Base64 para evitar errores de codificación en las cabeceras RFC 822
            String encodedSubject = "=?UTF-8?B?" + 
                Base64.getEncoder().encodeToString(subject.getBytes(StandardCharsets.UTF_8)) + 
                "?=";

            // 3. Construir el mensaje RFC 822 en formato MIME HTML
            String rawMessage = "To: " + recipient + "\r\n" +
                                "Subject: " + encodedSubject + "\r\n" +
                                "Content-Type: text/html; charset=UTF-8\r\n\r\n" +
                                body;

            // 3. Codificar en Base64 URL Safe (requerido por la API de Gmail)
            String encodedEmail = Base64.getUrlEncoder().withoutPadding().encodeToString(rawMessage.getBytes(StandardCharsets.UTF_8));

            // 4. Preparar cabeceras HTTP con el Bearer Token obtenido dinámicamente
            HttpHeaders headers = new HttpHeaders();
            headers.setBearerAuth(accessTokenValido);
            headers.setContentType(MediaType.APPLICATION_JSON);

            Map<String, String> requestBody = new HashMap<>();
            requestBody.put("raw", encodedEmail);

            HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);

            // 5. Consumir la API REST de Google para enviar el correo
            restTemplate.postForEntity(googleApiUrl, requestEntity, String.class);

            logger.info("Correo enviado exitosamente vía API REST Google OAuth2 a: {}", recipient);

        } catch (Exception e) {
            logger.error("Error al enviar correo vía Google API OAuth2 a {}: {}", recipient, e.getMessage(), e);
            throw new RuntimeException("Fallo en el envío mediante Google OAuth2", e);
        }
    }

    @Override
    public String armarBodySendMailUser(String ruta, String usuario, String saludo, String url,
                                        String accion, String minlong, String cantMay,
                                        String cantMin, String cantSimbo, String simPermi) {
        return String.format(
            "<html><body>" +
            "<div id='1' style='background-color: #F8F8F8;width: 875px;height: 550px;'>" +
                "<div style='margin:0 auto;text-align:center;background-color: #354856;width: 377px;height: 170px;'>" +
                    "<img style='margin-top: 40px;width: 200px;height: 87px;' src='%s' alt='logo'>" +
                "</div>" +
                "<div style='border:1px solid #FFF;margin:0 auto;background-color: #FFFFFF;width: 377px;height: 377px;'>" +
                    "<div>" +
                        "<div style='font-weight:bold;margin:15px auto 5px auto;text-align:center;color: #152228;font-family: Arial, sans-serif;font-size: 18px;'>" +
                            "Hola, <b>%s</b>" +
                        "</div>" +
                        "<div style='font-weight:bold;margin:12px auto 20px auto;color: #4c4c4d;font-family: Roboto, sans-serif;font-size: 15px;text-align:center;'>" +
                            " %s" +
                        "</div>" +
                    "</div>" +
                    "<div style='text-align:center;padding: 10px;'>" +
                        "<a style='background-color: #EA8B1D;border-radius: 9px;padding: 9px 86px;font-family: Arial, sans-serif;text-transform: uppercase;color:#fff;' href='%s'><b> %s </b></a>" +
                    "</div>" +
                    "<div style='background-color: #f5f3f3;border-radius: 6px;width: 266px;height: 170px;margin:10px auto 0 auto;'>" +
                        "<div style='padding:10px;color: #828386;font-family: Roboto, sans-serif;font-size: 14px;text-align: left;'>" +
                            "<div style='font-weight:bold;margin-bottom:7px;'>Le recordamos que la contraseña debe cumplir con los siguientes requerimientos:</div>" +
                            "<div style='padding:3px 0;'> &#10004; Longitud Mínima: %s </div>" +
                            "<div style='padding:3px 0;'> &#10004; Cantidad de Mayúsculas: %s </div>" +
                            "<div style='padding:3px 0;'> &#10004; Cantidad de Mínúsculas: %s </div>" +
                            "<div style='padding:3px 0;'> &#10004; Cantidad de Símbolos: %s </div>" +
                            "<div style='padding:3px 0;'> &#10004; Símbolos Permitidos: %s </div>" +
                        "</div>" +
                    "</div>" +
                "</div>" +
            "</div>" +
            "</body></html>",
            ruta, usuario, saludo, url, accion, minlong, cantMay, cantMin, cantSimbo, simPermi
        );
    }
}