package services

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"

	"github.com/sujit-baniya/fiber-boilerplate/pkg/models"
)

// EnviarCorreoGoogle manda un correo de texto plano vía Gmail API en nombre
// de la cuenta conectada. Asume que conexion ya pasó por RefrescarSiVence.
func EnviarCorreoGoogle(conexion *models.UmindConexion, destinatario, asunto, cuerpo string) error {
	accessToken, err := DescifrarSecretoUmind(conexion.AccessTokenEnc)
	if err != nil {
		return fmt.Errorf("no se pudo descifrar el access token: %w", err)
	}

	mime := fmt.Sprintf("To: %s\r\nSubject: %s\r\nContent-Type: text/plain; charset=\"UTF-8\"\r\n\r\n%s",
		destinatario, asunto, cuerpo)
	raw := base64.RawURLEncoding.EncodeToString([]byte(mime))

	body, _ := json.Marshal(map[string]string{"raw": raw})
	req, err := http.NewRequest(http.MethodPost, "https://gmail.googleapis.com/gmail/v1/users/me/messages/send", bytes.NewReader(body))
	if err != nil {
		return err
	}
	req.Header.Set("Authorization", "Bearer "+accessToken)
	req.Header.Set("Content-Type", "application/json")

	resp, err := umindOAuthHTTPClient.Do(req)
	if err != nil {
		return fmt.Errorf("no se pudo contactar Gmail: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		detalle, _ := io.ReadAll(io.LimitReader(resp.Body, 2048))
		return fmt.Errorf("Gmail respondió %d: %s", resp.StatusCode, string(detalle))
	}
	return nil
}

// LeerBandejaGoogle busca mensajes en Gmail (sintaxis de búsqueda de Gmail,
// ej: "from:cliente@ejemplo.com") y devuelve un resumen liviano de cada uno.
func LeerBandejaGoogle(conexion *models.UmindConexion, consulta string, limite int) ([]CorreoResumen, error) {
	if limite <= 0 || limite > 10 {
		limite = 10
	}
	accessToken, err := DescifrarSecretoUmind(conexion.AccessTokenEnc)
	if err != nil {
		return nil, fmt.Errorf("no se pudo descifrar el access token: %w", err)
	}

	listURL := fmt.Sprintf("https://gmail.googleapis.com/gmail/v1/users/me/messages?q=%s&maxResults=%d",
		url.QueryEscape(consulta), limite)
	var lista struct {
		Messages []struct {
			ID string `json:"id"`
		} `json:"messages"`
	}
	if err := gmailGetJSON(listURL, accessToken, &lista); err != nil {
		return nil, err
	}

	resultados := make([]CorreoResumen, 0, len(lista.Messages))
	for _, m := range lista.Messages {
		detalleURL := fmt.Sprintf("https://gmail.googleapis.com/gmail/v1/users/me/messages/%s?format=metadata&metadataHeaders=From&metadataHeaders=Subject&metadataHeaders=Date", m.ID)
		var msg struct {
			Snippet string `json:"snippet"`
			Payload struct {
				Headers []struct {
					Name  string `json:"name"`
					Value string `json:"value"`
				} `json:"headers"`
			} `json:"payload"`
		}
		if err := gmailGetJSON(detalleURL, accessToken, &msg); err != nil {
			continue // un mensaje individual que falla no debe tirar abajo toda la búsqueda
		}
		r := CorreoResumen{Extracto: msg.Snippet}
		for _, h := range msg.Payload.Headers {
			switch h.Name {
			case "From":
				r.De = h.Value
			case "Subject":
				r.Asunto = h.Value
			case "Date":
				r.Fecha = h.Value
			}
		}
		resultados = append(resultados, r)
	}
	return resultados, nil
}

func gmailGetJSON(url, accessToken string, out interface{}) error {
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return err
	}
	req.Header.Set("Authorization", "Bearer "+accessToken)
	resp, err := umindOAuthHTTPClient.Do(req)
	if err != nil {
		return fmt.Errorf("no se pudo contactar Gmail: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		detalle, _ := io.ReadAll(io.LimitReader(resp.Body, 2048))
		return fmt.Errorf("Gmail respondió %d: %s", resp.StatusCode, string(detalle))
	}
	return json.NewDecoder(resp.Body).Decode(out)
}
