package models

import (
	"fmt"
	"strings"

	"odoo-go/pkg/orm"
)

// RenderReportHTML generates an HTML table for a report type.
// Mirrors: odoo/addons/account_reports/models/account_report.py _get_html()
//
// Supports: trial_balance, balance_sheet, profit_loss, aged_receivable,
// aged_payable, general_ledger.
func RenderReportHTML(env *orm.Environment, reportType string) (string, error) {
	var data interface{}
	var err error

	switch reportType {
	case "trial_balance":
		data, err = generateTrialBalance(env)
	case "balance_sheet":
		data, err = generateBalanceSheet(env)
	case "profit_loss":
		data, err = generateProfitLoss(env)
	case "aged_receivable":
		data, err = generateAgedReport(env, "asset_receivable")
	case "aged_payable":
		data, err = generateAgedReport(env, "liability_payable")
	case "general_ledger":
		data, err = generateGeneralLedger(env)
	default:
		return "", fmt.Errorf("unknown report: %s", reportType)
	}
	if err != nil {
		return "", err
	}

	result, ok := data.(map[string]interface{})
	if !ok {
		return "", fmt.Errorf("invalid report data")
	}
	lines, _ := result["lines"].([]map[string]interface{})

	var b strings.Builder
	b.WriteString(`<!DOCTYPE html><html><head><meta charset="utf-8"><style>
		body{font-family:Arial,Helvetica,sans-serif;margin:20px;color:#333}
		table{width:100%;border-collapse:collapse;margin-top:12px}
		th,td{border:1px solid #ddd;padding:6px 8px;text-align:right}
		th{background:#875a7b;color:white;font-weight:600}
		td:first-child,th:first-child{text-align:left}
		tr:last-child{font-weight:bold;background:#f5f5f5}
		tr:hover{background:#faf5f8}
		h2{color:#875a7b;margin-bottom:4px}
		.report-date{color:#888;font-size:0.85em;margin-bottom:12px}
	</style></head><body>`)

	// Build table based on report type
	switch reportType {
	case "trial_balance":
		b.WriteString("<h2>Trial Balance</h2>")
		b.WriteString(`<table><tr><th>Code</th><th>Account</th><th>Debit</th><th>Credit</th><th>Balance</th></tr>`)
		for _, l := range lines {
			b.WriteString(fmt.Sprintf("<tr><td>%v</td><td>%v</td><td>%.2f</td><td>%.2f</td><td>%.2f</td></tr>",
				l["code"], l["name"], toF(l["debit"]), toF(l["credit"]), toF(l["balance"])))
		}
		b.WriteString("</table>")

	case "balance_sheet":
		b.WriteString("<h2>Balance Sheet</h2>")
		b.WriteString(`<table><tr><th>Section</th><th>Code</th><th>Account</th><th>Balance</th></tr>`)
		for _, l := range lines {
			b.WriteString(fmt.Sprintf("<tr><td>%v</td><td>%v</td><td>%v</td><td>%.2f</td></tr>",
				l["section"], l["code"], l["name"], toF(l["balance"])))
		}
		b.WriteString("</table>")

	case "profit_loss":
		b.WriteString("<h2>Profit &amp; Loss</h2>")
		b.WriteString(`<table><tr><th>Section</th><th>Code</th><th>Account</th><th>Amount</th></tr>`)
		for _, l := range lines {
			b.WriteString(fmt.Sprintf("<tr><td>%v</td><td>%v</td><td>%v</td><td>%.2f</td></tr>",
				l["section"], l["code"], l["name"], toF(l["balance"])))
		}
		b.WriteString("</table>")

	case "aged_receivable", "aged_payable":
		title := "Aged Receivable"
		if reportType == "aged_payable" {
			title = "Aged Payable"
		}
		b.WriteString(fmt.Sprintf("<h2>%s</h2>", title))
		b.WriteString(`<table><tr><th>Partner</th><th>Current</th><th>1-30</th><th>31-60</th><th>61-90+</th><th>Total</th></tr>`)
		for _, l := range lines {
			b.WriteString(fmt.Sprintf("<tr><td>%v</td><td>%.2f</td><td>%.2f</td><td>%.2f</td><td>%.2f</td><td>%.2f</td></tr>",
				l["partner"], toF(l["current"]), toF(l["1-30"]), toF(l["31-60"]), toF(l["61-90+"]), toF(l["total"])))
		}
		b.WriteString("</table>")

	case "general_ledger":
		b.WriteString("<h2>General Ledger</h2>")
		b.WriteString(`<table><tr><th>Account</th><th>Move</th><th>Date</th><th>Label</th><th>Debit</th><th>Credit</th></tr>`)
		for _, l := range lines {
			b.WriteString(fmt.Sprintf("<tr><td>%v %v</td><td>%v</td><td>%v</td><td>%v</td><td>%.2f</td><td>%.2f</td></tr>",
				l["account_code"], l["account_name"], l["move"], l["date"], l["label"],
				toF(l["debit"]), toF(l["credit"])))
		}
		b.WriteString("</table>")
	}

	b.WriteString("</body></html>")

	return b.String(), nil
}

// toF converts various numeric types to float64 for formatting.
func toF(v interface{}) float64 {
	switch n := v.(type) {
	case float64:
		return n
	case int64:
		return float64(n)
	case int:
		return float64(n)
	case int32:
		return float64(n)
	}
	return 0
}
