package snailmail

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
)

type cloudflareSender struct{}

type cfEmailRequest struct {
	To      string `json:"to"`
	From    string `json:"from"`
	Subject string `json:"subject"`
	HTML    string `json:"html,omitempty"`
	Text    string `json:"text,omitempty"`
}

type cfEmailResponse struct {
	Success bool `json:"success"`
	Errors  []struct {
		Code    int    `json:"code"`
		Message string `json:"message"`
	} `json:"errors"`
}

func (c *cloudflareSender) Send(message Email, mailtype int) error {
	if len(message.Recipients) == 0 {
		return fmt.Errorf("cloudflare email: no recipients")
	}

	req := cfEmailRequest{
		To:      message.Recipients[0],
		From:    settings.Cloudflare.FromAddress,
		Subject: message.Subject,
	}

	if mailtype == TYPE_HTML {
		req.HTML = message.Body.String()
	} else {
		req.Text = message.Body.String()
	}

	body, err := json.Marshal(req)
	if err != nil {
		return fmt.Errorf("cloudflare email: failed to marshal request: %w", err)
	}

	url := fmt.Sprintf("https://api.cloudflare.com/client/v4/accounts/%s/email/sending/send", settings.Cloudflare.AccountID)

	httpReq, err := http.NewRequest("POST", url, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("cloudflare email: failed to create request: %w", err)
	}

	httpReq.Header.Set("Authorization", "Bearer "+settings.Cloudflare.APIToken)
	httpReq.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(httpReq)
	if err != nil {
		log.Println("cloudflare email: request failed:", err)
		return fmt.Errorf("cloudflare email: request failed: %w", err)
	}
	defer resp.Body.Close()

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("cloudflare email: failed to read response: %w", err)
	}

	var cfResp cfEmailResponse
	if err := json.Unmarshal(respBody, &cfResp); err != nil {
		return fmt.Errorf("cloudflare email: failed to parse response: %w", err)
	}

	if !cfResp.Success {
		errMsg := "unknown error"
		if len(cfResp.Errors) > 0 {
			errMsg = cfResp.Errors[0].Message
		}
		log.Printf("cloudflare email: send failed: %s (HTTP %d)", errMsg, resp.StatusCode)
		return fmt.Errorf("cloudflare email: %s", errMsg)
	}

	return nil
}
