package documents

import (
	"bytes"
	"fmt"
	"os"
	"strings"
	"text/template"
	"time"

	"github.com/shopspring/decimal"
	"github.com/tech/sendico/billing/documents/internal/content"
	"github.com/tech/sendico/billing/documents/renderer"
	"github.com/tech/sendico/billing/documents/storage/model"
)

type templateRenderer struct {
	tpl *template.Template
}

type acceptanceTemplateData struct {
	model.ActSnapshot
	Content content.AcceptanceTemplateContent
}

func newTemplateRenderer(path string) (*templateRenderer, error) {
	//nolint:gosec // template file path is provided by trusted service configuration.
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read template: %w", err)
	}

	funcs := template.FuncMap{
		"money": formatMoney,
		"date":  formatDate,
	}

	tpl, err := template.New("acceptance").Funcs(funcs).Option("missingkey=error").Parse(string(data))
	if err != nil {
		return nil, fmt.Errorf("parse template: %w", err)
	}

	return &templateRenderer{tpl: tpl}, nil
}

func (r *templateRenderer) Render(snapshot model.ActSnapshot) ([]renderer.Block, error) {
	var buf bytes.Buffer
	data := acceptanceTemplateData{
		ActSnapshot: snapshot,
		Content:     content.AcceptanceTemplate,
	}

	if err := r.tpl.Execute(&buf, data); err != nil {
		return nil, fmt.Errorf("execute template: %w", err)
	}

	return renderer.ParseBlocks(buf.String())
}

func formatMoney(amount decimal.Decimal, currency string) string {
	currency = strings.TrimSpace(currency)
	if currency == "" {
		return amount.String()
	}

	return fmt.Sprintf("%s %s", amount.String(), currency)
}

func formatDate(t time.Time) string {
	if t.IsZero() {
		return ""
	}

	return t.Format("2006-01-02")
}
