package service

import (
	"bytes"
	"fmt"
	"html/template"
	"os"
	"os/exec"
	"path/filepath"
)

func renderTemplateToPDF(templatePath string, data interface{}) ([]byte, error) {
	// Create template with custom functions
	funcMap := template.FuncMap{
		"add": func(a, b int) int {
			return a + b
		},
	}

	// Parse and execute HTML template
	tmpl, err := template.New(filepath.Base(templatePath)).Funcs(funcMap).ParseFiles(templatePath)
	if err != nil {
		return nil, fmt.Errorf("parse template: %w", err)
	}
	var htmlBuf bytes.Buffer
	if err := tmpl.Execute(&htmlBuf, data); err != nil {
		return nil, fmt.Errorf("execute template: %w", err)
	}

	// Write HTML to a temp file
	tmpDir, err := os.MkdirTemp("", "daily_report_")
	if err != nil {
		return nil, fmt.Errorf("tmp dir: %w", err)
	}
	defer os.RemoveAll(tmpDir)

	htmlPath := filepath.Join(tmpDir, "report.html")
	pdfPath := filepath.Join(tmpDir, "report.pdf")

	if err := os.WriteFile(htmlPath, htmlBuf.Bytes(), 0644); err != nil {
		return nil, fmt.Errorf("write html: %w", err)
	}

	// Use Chrome headless for better CSS rendering
	chromeArgs := []string{
		"--headless",
		"--disable-gpu",
		"--no-sandbox",
		"--disable-dev-shm-usage",
		"--print-to-pdf=" + pdfPath,
		"--print-to-pdf-no-header",
		"--print-to-pdf-no-footer",
		"--print-to-pdf-margin-top=0",
		"--print-to-pdf-margin-bottom=0",
		"--print-to-pdf-margin-left=0",
		"--print-to-pdf-margin-right=0",
		"--print-to-pdf-paper-width=210mm",
		"--print-to-pdf-paper-height=297mm",
		htmlPath,
	}

	// Try Google Chrome first, then Chromium, then wkhtmltopdf as fallback
	chromeCmd := exec.Command("google-chrome", chromeArgs...)
	if out, err := chromeCmd.CombinedOutput(); err != nil {
		// Fallback to Chromium
		chromiumCmd := exec.Command("chromium", chromeArgs...)
		if chromiumOut, err := chromiumCmd.CombinedOutput(); err != nil {
			// Final fallback to wkhtmltopdf
			wkhtmlArgs := []string{
				"--enable-local-file-access",
				"--dpi", "300",
				"--page-size", "A4",
				"--orientation", "Portrait",
				"--margin-top", "0",
				"--margin-bottom", "0",
				"--margin-left", "0",
				"--margin-right", "0",
				htmlPath,
				pdfPath,
			}
			wkhtmlCmd := exec.Command("wkhtmltopdf", wkhtmlArgs...)
			if wkhtmlOut, err := wkhtmlCmd.CombinedOutput(); err != nil {
				return nil, fmt.Errorf("all PDF generators failed. Chrome error: %v, Chromium error: %v, wkhtmltopdf error: %v, chrome output: %s, chromium output: %s, wkhtmltopdf output: %s", chromeCmd.Err, chromiumCmd.Err, err, string(out), string(chromiumOut), string(wkhtmlOut))
			}
		}
	}

	// Read PDF bytes
	pdfBytes, err := os.ReadFile(pdfPath)
	if err != nil {
		return nil, fmt.Errorf("read pdf: %w", err)
	}
	return pdfBytes, nil
}

func formatCurrency(amount float64) string {
	// Simple currency formatting: Rp with thousands separators
	// Note: For exact locale formatting, integrate a locale library later
	s := fmt.Sprintf("%.0f", amount) // Remove decimal places for cleaner display
	intPart := addThousandsSep(s)
	return "Rp " + intPart
}

func splitAmount(s string) (string, string) {
	for i := len(s) - 1; i >= 0; i-- {
		if s[i] == '.' {
			return s[:i], s[i+1:]
		}
	}
	return s, "00"
}

func addThousandsSep(s string) string {
	n := len(s)
	if n <= 3 {
		return s
	}
	var out bytes.Buffer
	pre := n % 3
	if pre > 0 {
		out.WriteString(s[:pre])
		if n > pre {
			out.WriteByte('.')
		}
	}
	for i := pre; i < n; i += 3 {
		out.WriteString(s[i : i+3])
		if i+3 < n {
			out.WriteByte('.')
		}
	}
	return out.String()
}
