package mailer

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	htmltemplate "html/template"
	"io"
	"net/http"
	"net/url"
	"strings"
	texttemplate "text/template"
	"time"

	"royal-pop-backend/internal/config"
	"royal-pop-backend/internal/orders"
)

const resendEndpoint = "https://api.resend.com/emails"

type ResendMailer struct {
	apiKey        string
	from          string
	replyTo       string
	storefrontURL string
	httpClient    *http.Client
}

type resendEmailRequest struct {
	From    string   `json:"from"`
	To      []string `json:"to"`
	Subject string   `json:"subject"`
	HTML    string   `json:"html,omitempty"`
	Text    string   `json:"text,omitempty"`
	ReplyTo string   `json:"reply_to,omitempty"`
}

type shippedEmailTemplateData struct {
	FirstName       string
	OrderID         string
	ShippedDate     string
	ShippingCarrier string
	TrackingNumber  string
	TrackingURL     string
	OrderImageURL   string
	OrderImageAlt   string
	Items           []string
	StorefrontURL   string
}

type cancelledEmailTemplateData struct {
	FirstName     string
	OrderID       string
	CancelledDate string
	RefundAmount  string
	OrderImageURL string
	OrderImageAlt string
	Items         []string
	StorefrontURL string
}

type paidEmailTemplateData struct {
	FirstName     string
	OrderID       string
	PaidDate      string
	PaidAmount    string
	OrderImageURL string
	OrderImageAlt string
	Items         []string
	StorefrontURL string
}

type createdEmailTemplateData struct {
	OrderID            string
	CreatedDate        string
	OrderAmount        string
	CustomerName       string
	CustomerEmail      string
	OrderImageURL      string
	OrderImageAlt      string
	Items              []string
	StorefrontURL      string
	ClientDashboardURL string
}

type deliveredEmailTemplateData struct {
	FirstName     string
	OrderID       string
	DeliveredDate string
	OrderImageURL string
	OrderImageAlt string
	Items         []string
	StorefrontURL string
}

var shippedEmailHTMLTemplate = htmltemplate.Must(htmltemplate.New("shipped-email-html").Parse(`<!doctype html>
<html lang="en">
  <body style="margin:0;padding:0;background:#f7f7f7;color:#111827;font-family:Arial,sans-serif;">
    <div style="max-width:640px;margin:0 auto;padding:32px 20px;">
      <div style="background:#ffffff;border-radius:18px;padding:32px;box-shadow:0 18px 44px rgba(15,23,42,0.08);">
        <p style="margin:0 0 16px;font-size:16px;">Hi {{.FirstName}},</p>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">Your Royal Pop order is now on the way.</p>
		  <p style="margin:0 0 20px;font-size:16px;line-height:1.7;">
		    <strong>Order reference:</strong> {{.OrderID}}<br />
		    <strong>Shipped:</strong> {{.ShippedDate}}<br />
		    <strong>Carrier:</strong> {{.ShippingCarrier}}<br />
		    <strong>Tracking number:</strong> {{.TrackingNumber}}
		  </p>
		  {{if .OrderImageURL}}
		  <div style="margin:0 0 24px;">
		    <img src="{{.OrderImageURL}}" alt="{{.OrderImageAlt}}" style="display:block;width:100%;max-width:420px;height:auto;border-radius:16px;border:1px solid #e5e7eb;" />
		  </div>
		  {{end}}
		  {{if .TrackingURL}}
		  <p style="margin:0 0 24px;">
		    <a href="{{.TrackingURL}}" style="display:inline-block;padding:14px 22px;border-radius:999px;background:#111827;color:#ffffff;text-decoration:none;font-size:15px;font-weight:700;">Track your package</a>
		  </p>
		  {{end}}
		  <p style="margin:0 0 12px;font-size:16px;line-height:1.6;"><strong>In this shipment</strong></p>
		  <ul style="margin:0 0 20px 20px;padding:0;line-height:1.8;">
		    {{range .Items}}<li>{{.}}</li>{{end}}
        </ul>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">If you need anything, just reply to this email and we’ll help.</p>
        <p style="margin:0;font-size:16px;line-height:1.6;">Royal Pop</p>
      </div>
    </div>
  </body>
</html>`))

var shippedEmailTextTemplate = texttemplate.Must(texttemplate.New("shipped-email-text").Parse(`Hi {{.FirstName}},

Your Royal Pop order is now on the way.

Order reference: {{.OrderID}}
Shipped: {{.ShippedDate}}
Carrier: {{.ShippingCarrier}}
Tracking number: {{.TrackingNumber}}
{{if .TrackingURL}}Track your package: {{.TrackingURL}}

{{end}}

In this shipment:
{{range .Items}}- {{.}}
{{end}}

If you need anything, just reply to this email and we’ll help.

Royal Pop
`))

var cancelledEmailHTMLTemplate = htmltemplate.Must(htmltemplate.New("cancelled-email-html").Parse(`<!doctype html>
<html lang="en">
  <body style="margin:0;padding:0;background:#f7f7f7;color:#111827;font-family:Arial,sans-serif;">
    <div style="max-width:640px;margin:0 auto;padding:32px 20px;">
      <div style="background:#ffffff;border-radius:18px;padding:32px;box-shadow:0 18px 44px rgba(15,23,42,0.08);">
        <p style="margin:0 0 16px;font-size:16px;">Hi {{.FirstName}},</p>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">Your Royal Pop order has now been cancelled.</p>
        <p style="margin:0 0 20px;font-size:16px;line-height:1.7;">
          <strong>Order reference:</strong> {{.OrderID}}<br />
          <strong>Cancelled:</strong> {{.CancelledDate}}
        </p>
        {{if .OrderImageURL}}
        <div style="margin:0 0 24px;">
          <img src="{{.OrderImageURL}}" alt="{{.OrderImageAlt}}" style="display:block;width:100%;max-width:420px;height:auto;border-radius:16px;border:1px solid #e5e7eb;" />
        </div>
        {{end}}
        <p style="margin:0 0 16px;font-size:16px;line-height:1.7;">We were not able to complete this order because some of the information provided was missing or invalid.</p>
		<p style="margin:0 0 16px;font-size:16px;line-height:1.7;">A refund of <strong>{{.RefundAmount}}</strong> has now been issued to the original payment method. Depending on your bank or card provider, the refund may take a few business days to appear.</p>
        <p style="margin:0 0 12px;font-size:16px;line-height:1.6;"><strong>This cancelled order included</strong></p>
        <ul style="margin:0 0 20px 20px;padding:0;line-height:1.8;">
          {{range .Items}}<li>{{.}}</li>{{end}}
        </ul>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">If you would still like the order, just reply to this email and we’ll help you sort it out.</p>
        <p style="margin:0;font-size:16px;line-height:1.6;">Royal Pop</p>
      </div>
    </div>
  </body>
</html>`))

var cancelledEmailTextTemplate = texttemplate.Must(texttemplate.New("cancelled-email-text").Parse(`Hi {{.FirstName}},

Your Royal Pop order has now been cancelled.

Order reference: {{.OrderID}}
Cancelled: {{.CancelledDate}}

We were not able to complete this order because some of the information provided was missing or invalid.

A refund of {{.RefundAmount}} has now been issued to the original payment method. Depending on your bank or card provider, the refund may take a few business days to appear.

This cancelled order included:
{{range .Items}}- {{.}}
{{end}}

If you would still like the order, just reply to this email and we’ll help you sort it out.

Royal Pop
`))

var paidEmailHTMLTemplate = htmltemplate.Must(htmltemplate.New("paid-email-html").Parse(`<!doctype html>
<html lang="en">
  <body style="margin:0;padding:0;background:#f7f7f7;color:#111827;font-family:Arial,sans-serif;">
    <div style="max-width:640px;margin:0 auto;padding:32px 20px;">
      <div style="background:#ffffff;border-radius:18px;padding:32px;box-shadow:0 18px 44px rgba(15,23,42,0.08);">
        <p style="margin:0 0 16px;font-size:16px;">Hi {{.FirstName}},</p>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">We’ve received your Royal Pop order and your payment has gone through successfully.</p>
        <p style="margin:0 0 20px;font-size:16px;line-height:1.7;">
          <strong>Order reference:</strong> {{.OrderID}}<br />
          <strong>Paid:</strong> {{.PaidDate}}<br />
          <strong>Amount received:</strong> {{.PaidAmount}}
        </p>
        {{if .OrderImageURL}}
        <div style="margin:0 0 24px;">
          <img src="{{.OrderImageURL}}" alt="{{.OrderImageAlt}}" style="display:block;width:100%;max-width:420px;height:auto;border-radius:16px;border:1px solid #e5e7eb;" />
        </div>
        {{end}}
        <p style="margin:0 0 12px;font-size:16px;line-height:1.6;"><strong>Your order details</strong></p>
        <ul style="margin:0 0 20px 20px;padding:0;line-height:1.8;">
          {{range .Items}}<li>{{.}}</li>{{end}}
        </ul>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">We’ll email you again as soon as your order has been packed and shipped.</p>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">If you need anything in the meantime, just reply to this email and we’ll help.</p>
        <p style="margin:0;font-size:16px;line-height:1.6;">Royal Pop</p>
      </div>
    </div>
  </body>
</html>`))

var paidEmailTextTemplate = texttemplate.Must(texttemplate.New("paid-email-text").Parse(`Hi {{.FirstName}},

We’ve received your Royal Pop order and your payment has gone through successfully.

Order reference: {{.OrderID}}
Paid: {{.PaidDate}}
Amount received: {{.PaidAmount}}

Your order details:
{{range .Items}}- {{.}}
{{end}}

We’ll email you again as soon as your order has been packed and shipped.

If you need anything in the meantime, just reply to this email and we’ll help.

Royal Pop
`))

var createdEmailHTMLTemplate = htmltemplate.Must(htmltemplate.New("created-email-html").Parse(`<!doctype html>
<html lang="en">
  <body style="margin:0;padding:0;background:#f7f7f7;color:#111827;font-family:Arial,sans-serif;">
    <div style="max-width:640px;margin:0 auto;padding:32px 20px;">
      <div style="background:#ffffff;border-radius:18px;padding:32px;box-shadow:0 18px 44px rgba(15,23,42,0.08);">
		<p style="margin:0 0 16px;font-size:16px;">Hi,</p>
		<p style="margin:0 0 16px;font-size:16px;line-height:1.6;">A new paid Royal Pop order has been created and is ready for review in the client dashboard.</p>
		<p style="margin:0 0 20px;font-size:16px;line-height:1.7;">
		  <strong>Order reference:</strong> {{.OrderID}}<br />
		  <strong>Created:</strong> {{.CreatedDate}}<br />
		  <strong>Order total:</strong> {{.OrderAmount}}<br />
		  <strong>Customer:</strong> {{.CustomerName}}<br />
		  <strong>Customer email:</strong> {{.CustomerEmail}}
		</p>
		{{if .OrderImageURL}}
		<div style="margin:0 0 24px;">
		  <img src="{{.OrderImageURL}}" alt="{{.OrderImageAlt}}" style="display:block;width:100%;max-width:420px;height:auto;border-radius:16px;border:1px solid #e5e7eb;" />
		</div>
		{{end}}
		{{if .ClientDashboardURL}}
		<p style="margin:0 0 24px;">
		  <a href="{{.ClientDashboardURL}}" style="display:inline-block;padding:14px 22px;border-radius:999px;background:#111827;color:#ffffff;text-decoration:none;font-size:15px;font-weight:700;">Open client dashboard</a>
		</p>
		{{end}}
		<p style="margin:0 0 12px;font-size:16px;line-height:1.6;"><strong>Your order details</strong></p>
		<ul style="margin:0 0 20px 20px;padding:0;line-height:1.8;">
		  {{range .Items}}<li>{{.}}</li>{{end}}
        </ul>
		<p style="margin:0 0 16px;font-size:16px;line-height:1.6;">Use the dashboard to review the order, check stock, and continue fulfilment.</p>
		<p style="margin:0 0 16px;font-size:16px;line-height:1.6;">If you need anything, just reply to this email and we’ll help.</p>
		<p style="margin:0;font-size:16px;line-height:1.6;">Royal Pop</p>
      </div>
    </div>
  </body>
</html>`))

var createdEmailTextTemplate = texttemplate.Must(texttemplate.New("created-email-text").Parse(`Hi,

A new paid Royal Pop order has been created and is ready for review in the client dashboard.

Order reference: {{.OrderID}}
Created: {{.CreatedDate}}
Order total: {{.OrderAmount}}
Customer: {{.CustomerName}}
Customer email: {{.CustomerEmail}}

{{if .ClientDashboardURL}}Open client dashboard: {{.ClientDashboardURL}}

{{end}}

Your order details:
{{range .Items}}- {{.}}
{{end}}

Use the dashboard to review the order, check stock, and continue fulfilment.

If you need anything, just reply to this email and we’ll help.

Royal Pop
`))

var deliveredEmailHTMLTemplate = htmltemplate.Must(htmltemplate.New("delivered-email-html").Parse(`<!doctype html>
<html lang="en">
  <body style="margin:0;padding:0;background:#f7f7f7;color:#111827;font-family:Arial,sans-serif;">
    <div style="max-width:640px;margin:0 auto;padding:32px 20px;">
      <div style="background:#ffffff;border-radius:18px;padding:32px;box-shadow:0 18px 44px rgba(15,23,42,0.08);">
        <p style="margin:0 0 16px;font-size:16px;">Hi {{.FirstName}},</p>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">Your Royal Pop order has been delivered.</p>
        <p style="margin:0 0 20px;font-size:16px;line-height:1.7;">
          <strong>Order reference:</strong> {{.OrderID}}<br />
          <strong>Delivered:</strong> {{.DeliveredDate}}
        </p>
        {{if .OrderImageURL}}
        <div style="margin:0 0 24px;">
          <img src="{{.OrderImageURL}}" alt="{{.OrderImageAlt}}" style="display:block;width:100%;max-width:420px;height:auto;border-radius:16px;border:1px solid #e5e7eb;" />
        </div>
        {{end}}
        <p style="margin:0 0 12px;font-size:16px;line-height:1.6;"><strong>Your delivered order</strong></p>
        <ul style="margin:0 0 20px 20px;padding:0;line-height:1.8;">
          {{range .Items}}<li>{{.}}</li>{{end}}
        </ul>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">Thank you for your order — we hope you love it.</p>
        <p style="margin:0 0 16px;font-size:16px;line-height:1.6;">If you need anything at all, just reply to this email and we’ll help.</p>
        <p style="margin:0;font-size:16px;line-height:1.6;">Royal Pop</p>
      </div>
    </div>
  </body>
</html>`))

var deliveredEmailTextTemplate = texttemplate.Must(texttemplate.New("delivered-email-text").Parse(`Hi {{.FirstName}},

Your Royal Pop order has been delivered.

Order reference: {{.OrderID}}
Delivered: {{.DeliveredDate}}

Your delivered order:
{{range .Items}}- {{.}}
{{end}}

Thank you for your order — we hope you love it.

If you need anything at all, just reply to this email and we’ll help.

Royal Pop
`))

var colorwayNames = map[string]string{
	"ocho-negro":             "ONYX",
	"pure-white":             "BLANC",
	"pop-pink":               "SAKURA",
	"racer-green":            "FOREST",
	"lime-blue":              "SAGE",
	"deep-blue-orange":       "MIDNIGHT",
	"light-blue-sprint":      "GLACIER",
	"sorbet-pop-multi-color": "SORBET",
}

var finishNames = map[string]string{
	"silver":    "Silver",
	"black-pvd": "Black PVD",
	"rose-gold": "Rose Gold",
}

func NewResendMailer(cfg *config.Config) *ResendMailer {
	if cfg == nil {
		return &ResendMailer{}
	}

	return &ResendMailer{
		apiKey:        strings.TrimSpace(cfg.ResendAPIKey),
		from:          strings.TrimSpace(cfg.ResendOrderFrom),
		replyTo:       strings.TrimSpace(cfg.ResendForward),
		storefrontURL: normalizeStorefrontURL(cfg.StorefrontURL),
		httpClient: &http.Client{
			Timeout: 15 * time.Second,
		},
	}
}

func (m *ResendMailer) Enabled() bool {
	if m == nil {
		return false
	}

	return strings.TrimSpace(m.apiKey) != "" && strings.TrimSpace(m.from) != ""
}

func (m *ResendMailer) SendOrderShipped(ctx context.Context, order *orders.Order) error {
	if order == nil {
		return fmt.Errorf("order is required")
	}
	if !m.Enabled() {
		return fmt.Errorf("resend mailer is not configured")
	}

	payload, err := m.buildShippedEmailRequest(order)
	if err != nil {
		return err
	}

	body, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal resend payload: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, resendEndpoint, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("create resend request: %w", err)
	}

	req.Header.Set("Authorization", "Bearer "+m.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := m.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("send resend request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return nil
	}

	responseBody, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
	message := strings.TrimSpace(string(responseBody))
	if message == "" {
		message = resp.Status
	}

	return fmt.Errorf("resend email failed: %s", message)
}

func (m *ResendMailer) SendOrderCancelled(ctx context.Context, order *orders.Order) error {
	if order == nil {
		return fmt.Errorf("order is required")
	}
	if !m.Enabled() {
		return fmt.Errorf("resend mailer is not configured")
	}

	payload, err := m.buildCancelledEmailRequest(order)
	if err != nil {
		return err
	}

	body, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal resend payload: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, resendEndpoint, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("create resend request: %w", err)
	}

	req.Header.Set("Authorization", "Bearer "+m.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := m.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("send resend request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return nil
	}

	responseBody, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
	message := strings.TrimSpace(string(responseBody))
	if message == "" {
		message = resp.Status
	}

	return fmt.Errorf("resend email failed: %s", message)
}

func (m *ResendMailer) SendOrderPaid(ctx context.Context, order *orders.Order) error {
	if order == nil {
		return fmt.Errorf("order is required")
	}
	if !m.Enabled() {
		return fmt.Errorf("resend mailer is not configured")
	}

	payload, err := m.buildPaidEmailRequest(order)
	if err != nil {
		return err
	}

	body, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal resend payload: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, resendEndpoint, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("create resend request: %w", err)
	}

	req.Header.Set("Authorization", "Bearer "+m.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := m.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("send resend request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return nil
	}

	responseBody, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
	message := strings.TrimSpace(string(responseBody))
	if message == "" {
		message = resp.Status
	}

	return fmt.Errorf("resend email failed: %s", message)
}

func (m *ResendMailer) SendOrderCreated(ctx context.Context, order *orders.Order) error {
	if order == nil {
		return fmt.Errorf("order is required")
	}
	if !m.Enabled() {
		return fmt.Errorf("resend mailer is not configured")
	}

	payload, err := m.buildCreatedEmailRequest(order)
	if err != nil {
		return err
	}

	body, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal resend payload: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, resendEndpoint, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("create resend request: %w", err)
	}

	req.Header.Set("Authorization", "Bearer "+m.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := m.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("send resend request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return nil
	}

	responseBody, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
	message := strings.TrimSpace(string(responseBody))
	if message == "" {
		message = resp.Status
	}

	return fmt.Errorf("resend email failed: %s", message)
}

func (m *ResendMailer) SendOrderDelivered(ctx context.Context, order *orders.Order) error {
	if order == nil {
		return fmt.Errorf("order is required")
	}
	if !m.Enabled() {
		return fmt.Errorf("resend mailer is not configured")
	}

	payload, err := m.buildDeliveredEmailRequest(order)
	if err != nil {
		return err
	}

	body, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("marshal resend payload: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, resendEndpoint, bytes.NewReader(body))
	if err != nil {
		return fmt.Errorf("create resend request: %w", err)
	}

	req.Header.Set("Authorization", "Bearer "+m.apiKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := m.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("send resend request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		return nil
	}

	responseBody, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
	message := strings.TrimSpace(string(responseBody))
	if message == "" {
		message = resp.Status
	}

	return fmt.Errorf("resend email failed: %s", message)
}

func (m *ResendMailer) buildShippedEmailRequest(order *orders.Order) (*resendEmailRequest, error) {
	data := shippedEmailTemplateData{
		FirstName:       firstNonEmpty(strings.TrimSpace(order.FirstName), "there"),
		OrderID:         strings.TrimSpace(order.ID),
		ShippedDate:     shippedDateLabel(order),
		ShippingCarrier: strings.TrimSpace(order.ShippingCarrier),
		TrackingNumber:  strings.TrimSpace(order.TrackingNumber),
		TrackingURL:     buildTrackingURL(order.ShippingCarrier, order.TrackingNumber),
		OrderImageURL:   buildOrderImageURL(m.storefrontURL, order.Items),
		OrderImageAlt:   buildOrderImageAlt(order.Items),
		Items:           buildShipmentLineItems(order.Items),
		StorefrontURL:   m.storefrontURL,
	}

	var htmlBody bytes.Buffer
	if err := shippedEmailHTMLTemplate.Execute(&htmlBody, data); err != nil {
		return nil, fmt.Errorf("render shipment email html: %w", err)
	}

	var textBody bytes.Buffer
	if err := shippedEmailTextTemplate.Execute(&textBody, data); err != nil {
		return nil, fmt.Errorf("render shipment email text: %w", err)
	}

	return &resendEmailRequest{
		From:    m.from,
		To:      []string{strings.TrimSpace(order.Email)},
		Subject: fmt.Sprintf("Your Royal Pop order is on the way — %s", data.OrderID),
		HTML:    htmlBody.String(),
		Text:    textBody.String(),
		ReplyTo: m.replyTo,
	}, nil
}

func (m *ResendMailer) buildCancelledEmailRequest(order *orders.Order) (*resendEmailRequest, error) {
	data := cancelledEmailTemplateData{
		FirstName:     firstNonEmpty(strings.TrimSpace(order.FirstName), "there"),
		OrderID:       strings.TrimSpace(order.ID),
		CancelledDate: cancelledDateLabel(order),
		RefundAmount:  formatMoney(order.Currency, order.Amount),
		OrderImageURL: buildOrderImageURL(m.storefrontURL, order.Items),
		OrderImageAlt: buildOrderImageAlt(order.Items),
		Items:         buildShipmentLineItems(order.Items),
		StorefrontURL: m.storefrontURL,
	}

	var htmlBody bytes.Buffer
	if err := cancelledEmailHTMLTemplate.Execute(&htmlBody, data); err != nil {
		return nil, fmt.Errorf("render cancelled email html: %w", err)
	}

	var textBody bytes.Buffer
	if err := cancelledEmailTextTemplate.Execute(&textBody, data); err != nil {
		return nil, fmt.Errorf("render cancelled email text: %w", err)
	}

	return &resendEmailRequest{
		From:    m.from,
		To:      []string{strings.TrimSpace(order.Email)},
		Subject: fmt.Sprintf("Your Royal Pop order has been cancelled — %s", data.OrderID),
		HTML:    htmlBody.String(),
		Text:    textBody.String(),
		ReplyTo: m.replyTo,
	}, nil
}

func (m *ResendMailer) buildPaidEmailRequest(order *orders.Order) (*resendEmailRequest, error) {
	data := paidEmailTemplateData{
		FirstName:     firstNonEmpty(strings.TrimSpace(order.FirstName), "there"),
		OrderID:       strings.TrimSpace(order.ID),
		PaidDate:      paidDateLabel(order),
		PaidAmount:    formatMoney(order.Currency, order.Amount),
		OrderImageURL: buildOrderImageURL(m.storefrontURL, order.Items),
		OrderImageAlt: buildOrderImageAlt(order.Items),
		Items:         buildShipmentLineItems(order.Items),
		StorefrontURL: m.storefrontURL,
	}

	var htmlBody bytes.Buffer
	if err := paidEmailHTMLTemplate.Execute(&htmlBody, data); err != nil {
		return nil, fmt.Errorf("render paid email html: %w", err)
	}

	var textBody bytes.Buffer
	if err := paidEmailTextTemplate.Execute(&textBody, data); err != nil {
		return nil, fmt.Errorf("render paid email text: %w", err)
	}

	return &resendEmailRequest{
		From:    m.from,
		To:      []string{strings.TrimSpace(order.Email)},
		Subject: fmt.Sprintf("We’ve received your Royal Pop order — %s", data.OrderID),
		HTML:    htmlBody.String(),
		Text:    textBody.String(),
		ReplyTo: m.replyTo,
	}, nil
}

func (m *ResendMailer) buildCreatedEmailRequest(order *orders.Order) (*resendEmailRequest, error) {
	data := createdEmailTemplateData{
		OrderID:            strings.TrimSpace(order.ID),
		CreatedDate:        createdDateLabel(order),
		OrderAmount:        formatMoney(order.Currency, order.Amount),
		CustomerName:       strings.TrimSpace(strings.Join([]string{strings.TrimSpace(order.FirstName), strings.TrimSpace(order.LastName)}, " ")),
		CustomerEmail:      strings.TrimSpace(order.Email),
		OrderImageURL:      buildOrderImageURL(m.storefrontURL, order.Items),
		OrderImageAlt:      buildOrderImageAlt(order.Items),
		Items:              buildShipmentLineItems(order.Items),
		StorefrontURL:      m.storefrontURL,
		ClientDashboardURL: buildClientDashboardURL(m.storefrontURL),
	}
	if data.CustomerName == "" {
		data.CustomerName = "Customer"
	}
	if data.CustomerEmail == "" {
		data.CustomerEmail = "Not provided"
	}

	var htmlBody bytes.Buffer
	if err := createdEmailHTMLTemplate.Execute(&htmlBody, data); err != nil {
		return nil, fmt.Errorf("render created email html: %w", err)
	}

	var textBody bytes.Buffer
	if err := createdEmailTextTemplate.Execute(&textBody, data); err != nil {
		return nil, fmt.Errorf("render created email text: %w", err)
	}

	return &resendEmailRequest{
		From:    m.from,
		To:      []string{firstNonEmpty(strings.TrimSpace(m.replyTo), strings.TrimSpace(m.from))},
		Subject: fmt.Sprintf("Client reminder: paid order created — %s", data.OrderID),
		HTML:    htmlBody.String(),
		Text:    textBody.String(),
		ReplyTo: m.replyTo,
	}, nil
}

func (m *ResendMailer) buildDeliveredEmailRequest(order *orders.Order) (*resendEmailRequest, error) {
	data := deliveredEmailTemplateData{
		FirstName:     firstNonEmpty(strings.TrimSpace(order.FirstName), "there"),
		OrderID:       strings.TrimSpace(order.ID),
		DeliveredDate: deliveredDateLabel(order),
		OrderImageURL: buildOrderImageURL(m.storefrontURL, order.Items),
		OrderImageAlt: buildOrderImageAlt(order.Items),
		Items:         buildShipmentLineItems(order.Items),
		StorefrontURL: m.storefrontURL,
	}

	var htmlBody bytes.Buffer
	if err := deliveredEmailHTMLTemplate.Execute(&htmlBody, data); err != nil {
		return nil, fmt.Errorf("render delivered email html: %w", err)
	}

	var textBody bytes.Buffer
	if err := deliveredEmailTextTemplate.Execute(&textBody, data); err != nil {
		return nil, fmt.Errorf("render delivered email text: %w", err)
	}

	return &resendEmailRequest{
		From:    m.from,
		To:      []string{strings.TrimSpace(order.Email)},
		Subject: fmt.Sprintf("Your Royal Pop order has been delivered — %s", data.OrderID),
		HTML:    htmlBody.String(),
		Text:    textBody.String(),
		ReplyTo: m.replyTo,
	}, nil
}

func buildClientDashboardURL(storefrontURL string) string {
	base := strings.TrimRight(strings.TrimSpace(storefrontURL), "/")
	if base == "" {
		base = "https://royal-pop-accessory.com"
	}

	return base + "/client"
}

func buildShipmentLineItems(items []orders.LineItem) []string {
	if len(items) == 0 {
		return []string{"Royal Pop order items"}
	}

	lines := make([]string, 0, len(items))
	for _, item := range items {
		quantity := item.Quantity
		if quantity <= 0 {
			quantity = 1
		}

		styleLabel := "Style " + strings.ToUpper(strings.TrimSpace(item.Style))
		if strings.TrimSpace(item.Style) == "" {
			styleLabel = "Style"
		}

		lines = append(lines, fmt.Sprintf(
			"%s · %s · %s · %s",
			firstNonEmpty(colorwayDisplayName(item.ColorwayID), "Royal Pop"),
			styleLabel,
			firstNonEmpty(finishDisplayName(item.FinishID), "Finish"),
			quantityLabel(quantity),
		))
	}

	return lines
}

func shippedDateLabel(order *orders.Order) string {
	if order == nil {
		return time.Now().UTC().Format("2 January 2006")
	}

	if order.ShippedAt != nil && !order.ShippedAt.IsZero() {
		return order.ShippedAt.UTC().Format("2 January 2006")
	}

	if !order.UpdatedAt.IsZero() {
		return order.UpdatedAt.UTC().Format("2 January 2006")
	}

	return time.Now().UTC().Format("2 January 2006")
}

func cancelledDateLabel(order *orders.Order) string {
	if order == nil {
		return time.Now().UTC().Format("2 January 2006")
	}

	if !order.UpdatedAt.IsZero() {
		return order.UpdatedAt.UTC().Format("2 January 2006")
	}

	return time.Now().UTC().Format("2 January 2006")
}

func paidDateLabel(order *orders.Order) string {
	if order == nil {
		return time.Now().UTC().Format("2 January 2006")
	}

	if !order.UpdatedAt.IsZero() {
		return order.UpdatedAt.UTC().Format("2 January 2006")
	}

	if !order.CreatedAt.IsZero() {
		return order.CreatedAt.UTC().Format("2 January 2006")
	}

	return time.Now().UTC().Format("2 January 2006")
}

func createdDateLabel(order *orders.Order) string {
	if order == nil {
		return time.Now().UTC().Format("2 January 2006")
	}

	if !order.CreatedAt.IsZero() {
		return order.CreatedAt.UTC().Format("2 January 2006")
	}

	if !order.UpdatedAt.IsZero() {
		return order.UpdatedAt.UTC().Format("2 January 2006")
	}

	return time.Now().UTC().Format("2 January 2006")
}

func deliveredDateLabel(order *orders.Order) string {
	if order == nil {
		return time.Now().UTC().Format("2 January 2006")
	}

	if !order.UpdatedAt.IsZero() {
		return order.UpdatedAt.UTC().Format("2 January 2006")
	}

	if order.ShippedAt != nil && !order.ShippedAt.IsZero() {
		return order.ShippedAt.UTC().Format("2 January 2006")
	}

	return time.Now().UTC().Format("2 January 2006")
}

func quantityLabel(quantity int64) string {
	if quantity == 1 {
		return "1 kit"
	}

	return fmt.Sprintf("%d kits", quantity)
}

func formatMoney(currency string, amount int64) string {
	code := strings.ToUpper(strings.TrimSpace(currency))
	major := float64(amount) / 100

	switch code {
	case "GBP", "":
		return fmt.Sprintf("£%.2f", major)
	case "USD":
		return fmt.Sprintf("$%.2f", major)
	case "EUR":
		return fmt.Sprintf("€%.2f", major)
	default:
		return fmt.Sprintf("%s %.2f", code, major)
	}
}

func colorwayDisplayName(id string) string {
	trimmed := strings.TrimSpace(id)
	if trimmed == "" {
		return ""
	}
	if label, ok := colorwayNames[trimmed]; ok {
		return label
	}

	return slugLabel(trimmed)
}

func finishDisplayName(id string) string {
	trimmed := strings.TrimSpace(id)
	if trimmed == "" {
		return ""
	}
	if label, ok := finishNames[trimmed]; ok {
		return label
	}

	return slugLabel(trimmed)
}

func slugLabel(value string) string {
	parts := strings.Fields(strings.ReplaceAll(strings.ReplaceAll(strings.TrimSpace(value), "-", " "), "_", " "))
	if len(parts) == 0 {
		return ""
	}

	formatted := make([]string, 0, len(parts))
	for _, part := range parts {
		formatted = append(formatted, strings.ToUpper(part[:1])+strings.ToLower(part[1:]))
	}

	return strings.Join(formatted, " ")
}

func firstNonEmpty(values ...string) string {
	for _, value := range values {
		if trimmed := strings.TrimSpace(value); trimmed != "" {
			return trimmed
		}
	}

	return ""
}

func normalizeStorefrontURL(raw string) string {
	trimmed := strings.TrimRight(strings.TrimSpace(raw), "/")
	if trimmed == "" {
		return "https://royal-pop-accessory.com"
	}

	lower := strings.ToLower(trimmed)
	if strings.Contains(lower, "localhost") || strings.Contains(lower, "127.0.0.1") || strings.Contains(lower, ".local") {
		return "https://royal-pop-accessory.com"
	}

	return trimmed
}

func buildTrackingURL(carrier, trackingNumber string) string {
	tracking := strings.TrimSpace(trackingNumber)
	if tracking == "" {
		return ""
	}

	return "https://www.17track.net/en/track#nums=" + url.QueryEscape(tracking)
}

func buildOrderImageURL(storefrontURL string, items []orders.LineItem) string {
	baseURL := strings.TrimRight(strings.TrimSpace(storefrontURL), "/")
	if baseURL == "" {
		return ""
	}

	imagePath := "/images/png/ocho-negro.png"
	if len(items) > 0 {
		colorwayID := strings.TrimSpace(items[0].ColorwayID)
		if mappedPath, ok := orderImagePathForColorway(colorwayID); ok {
			imagePath = mappedPath
		}
	}

	return baseURL + imagePath
}

func orderImagePathForColorway(colorwayID string) (string, bool) {
	switch strings.TrimSpace(colorwayID) {
	case "ocho-negro":
		return "/images/png/ocho-negro.png", true
	case "pure-white":
		return "/images/png/pure-white.png", true
	case "pop-pink":
		return "/images/png/pop-pink.png", true
	case "racer-green":
		return "/images/png/racer-green.png", true
	case "lime-blue":
		return "/images/png/lime-blue.png", true
	case "deep-blue-orange":
		return "/images/png/deep-blue.png", true
	case "light-blue-sprint":
		return "/images/png/light-blue.png", true
	case "sorbet-pop-multi-color":
		return "/images/png/sorbet-multi.png", true
	default:
		return "", false
	}
}

func buildOrderImageAlt(items []orders.LineItem) string {
	if len(items) == 0 {
		return "Royal Pop order preview"
	}

	colorway := colorwayDisplayName(items[0].ColorwayID)
	style := strings.ToUpper(strings.TrimSpace(items[0].Style))
	finish := finishDisplayName(items[0].FinishID)

	parts := make([]string, 0, 3)
	if colorway != "" {
		parts = append(parts, colorway)
	}
	if style != "" {
		parts = append(parts, "Style "+style)
	}
	if finish != "" {
		parts = append(parts, finish)
	}

	if len(parts) == 0 {
		return "Royal Pop order preview"
	}

	return strings.Join(parts, " · ") + " order preview"
}
