package models

import (
	"fmt"

	"odoo-go/pkg/orm"
)

// initSaleOrderTemplate registers sale.order.template and sale.order.template.line.
// Mirrors: odoo/addons/sale_management/models/sale_order_template.py
//
//	class SaleOrderTemplate(models.Model):
//	    _name = 'sale.order.template'
//	    _description = 'Quotation Template'
func initSaleOrderTemplate() {
	m := orm.NewModel("sale.order.template", orm.ModelOpts{
		Description: "Quotation Template",
		Order:       "sequence, id",
	})

	// -- Identity --
	m.AddFields(
		orm.Char("name", orm.FieldOpts{String: "Name", Required: true, Translate: true}),
		orm.Many2one("company_id", "res.company", orm.FieldOpts{String: "Company"}),
		orm.Integer("number_of_days", orm.FieldOpts{String: "Validity (Days)", Default: 30}),
		orm.Text("note", orm.FieldOpts{String: "Terms and Conditions", Translate: true}),
		orm.Boolean("active", orm.FieldOpts{String: "Active", Default: true}),
		orm.Integer("sequence", orm.FieldOpts{String: "Sequence", Default: 10}),
		orm.Many2one("mail_template_id", "mail.template", orm.FieldOpts{String: "Confirmation Mail"}),
	)

	// -- Lines --
	m.AddFields(
		orm.One2many("sale_order_template_line_ids", "sale.order.template.line", "sale_order_template_id", orm.FieldOpts{
			String: "Lines",
		}),
		orm.One2many("sale_order_template_option_ids", "sale.order.template.option", "sale_order_template_id", orm.FieldOpts{
			String: "Optional Products",
		}),
	)

	// -- Computed: line_count --
	m.AddFields(
		orm.Integer("line_count", orm.FieldOpts{
			String: "Line Count", Compute: "_compute_line_count",
		}),
	)
	m.RegisterCompute("line_count", func(rs *orm.Recordset) (orm.Values, error) {
		env := rs.Env()
		templateID := rs.IDs()[0]
		var count int
		err := env.Tx().QueryRow(env.Ctx(),
			`SELECT COUNT(*) FROM sale_order_template_line WHERE sale_order_template_id = $1`,
			templateID).Scan(&count)
		if err != nil {
			count = 0
		}
		return orm.Values{"line_count": count}, nil
	})

	// action_apply_to_order: Apply this template to a sale order.
	// Mirrors: odoo/addons/sale_management/models/sale_order.py SaleOrder._onchange_sale_order_template_id()
	// Copies template lines into the SO as order lines, and copies the template note.
	m.RegisterMethod("action_apply_to_order", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
		if len(args) < 1 {
			return nil, fmt.Errorf("order_id required")
		}
		env := rs.Env()
		templateID := rs.IDs()[0]
		orderID, _ := args[0].(float64)

		// Read template lines
		rows, err := env.Tx().Query(env.Ctx(),
			`SELECT name, product_id, product_uom_qty, price_unit, discount, sequence
			 FROM sale_order_template_line
			 WHERE sale_order_template_id = $1 ORDER BY sequence`, templateID)
		if err != nil {
			return nil, fmt.Errorf("sale_template: read lines: %w", err)
		}
		defer rows.Close()

		lineRS := env.Model("sale.order.line")
		for rows.Next() {
			var name string
			var prodID *int64
			var qty, price, disc float64
			var seq int
			if err := rows.Scan(&name, &prodID, &qty, &price, &disc, &seq); err != nil {
				return nil, fmt.Errorf("sale_template: scan line: %w", err)
			}
			vals := orm.Values{
				"order_id":        int64(orderID),
				"name":            name,
				"product_uom_qty": qty,
				"price_unit":      price,
				"discount":        disc,
				"sequence":        seq,
			}
			if prodID != nil {
				vals["product_id"] = *prodID
			}
			if _, err := lineRS.Create(vals); err != nil {
				return nil, fmt.Errorf("sale_template: create SO line: %w", err)
			}
		}

		// Copy template note to the SO
		var note *string
		env.Tx().QueryRow(env.Ctx(),
			`SELECT note FROM sale_order_template WHERE id = $1`, templateID).Scan(&note)
		if note != nil {
			env.Tx().Exec(env.Ctx(),
				`UPDATE sale_order SET note = $1 WHERE id = $2`, *note, int64(orderID))
		}

		// Copy validity_date from number_of_days
		var numDays int
		env.Tx().QueryRow(env.Ctx(),
			`SELECT COALESCE(number_of_days, 0) FROM sale_order_template WHERE id = $1`,
			templateID).Scan(&numDays)
		if numDays > 0 {
			env.Tx().Exec(env.Ctx(),
				`UPDATE sale_order SET validity_date = CURRENT_DATE + $1 WHERE id = $2`,
				numDays, int64(orderID))
		}

		return true, nil
	})

	// action_open_template: Return an action to open this template's form view.
	// Mirrors: odoo/addons/sale_management/models/sale_order_template.py
	m.RegisterMethod("action_open_template", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
		templateID := rs.IDs()[0]
		return map[string]interface{}{
			"type":      "ir.actions.act_window",
			"res_model": "sale.order.template",
			"res_id":    templateID,
			"view_mode": "form",
			"views":     [][]interface{}{{nil, "form"}},
			"target":    "current",
		}, nil
	})
}

// initSaleOrderTemplateLine registers sale.order.template.line.
// Mirrors: odoo/addons/sale_management/models/sale_order_template.py SaleOrderTemplateLine
func initSaleOrderTemplateLine() {
	m := orm.NewModel("sale.order.template.line", orm.ModelOpts{
		Description: "Quotation Template Line",
		Order:       "sequence, id",
	})

	m.AddFields(
		orm.Many2one("sale_order_template_id", "sale.order.template", orm.FieldOpts{
			String: "Template", Required: true, OnDelete: orm.OnDeleteCascade, Index: true,
		}),
		orm.Many2one("product_id", "product.product", orm.FieldOpts{String: "Product"}),
		orm.Char("name", orm.FieldOpts{String: "Description", Required: true, Translate: true}),
		orm.Float("product_uom_qty", orm.FieldOpts{String: "Quantity", Default: 1}),
		orm.Many2one("product_uom_id", "uom.uom", orm.FieldOpts{String: "Unit of Measure"}),
		orm.Float("price_unit", orm.FieldOpts{String: "Unit Price"}),
		orm.Float("discount", orm.FieldOpts{String: "Discount (%)"}),
		orm.Integer("sequence", orm.FieldOpts{String: "Sequence", Default: 10}),
		orm.Selection("display_type", []orm.SelectionItem{
			{Value: "line_section", Label: "Section"},
			{Value: "line_note", Label: "Note"},
		}, orm.FieldOpts{String: "Display Type"}),
		orm.Many2one("company_id", "res.company", orm.FieldOpts{String: "Company"}),
	)

	// Onchange: product_id → name + price_unit
	// Mirrors: odoo/addons/sale_management/models/sale_order_template.py SaleOrderTemplateLine._compute_name()
	m.RegisterOnchange("product_id", func(env *orm.Environment, vals orm.Values) orm.Values {
		result := make(orm.Values)

		var productID int64
		switch v := vals["product_id"].(type) {
		case int64:
			productID = v
		case float64:
			productID = int64(v)
		case map[string]interface{}:
			if id, ok := v["id"]; ok {
				switch n := id.(type) {
				case float64:
					productID = int64(n)
				case int64:
					productID = n
				}
			}
		}
		if productID <= 0 {
			return result
		}

		var name string
		var listPrice float64
		err := env.Tx().QueryRow(env.Ctx(),
			`SELECT COALESCE(pt.name, ''), COALESCE(pt.list_price, 0)
			 FROM product_product pp
			 JOIN product_template pt ON pt.id = pp.product_tmpl_id
			 WHERE pp.id = $1`, productID,
		).Scan(&name, &listPrice)
		if err != nil {
			return result
		}

		result["name"] = name
		result["price_unit"] = listPrice
		return result
	})

	// _compute_price_subtotal: qty * price * (1 - discount/100)
	m.AddFields(
		orm.Monetary("price_subtotal", orm.FieldOpts{
			String: "Subtotal", Compute: "_compute_price_subtotal", CurrencyField: "currency_id",
		}),
	)
	m.RegisterCompute("price_subtotal", func(rs *orm.Recordset) (orm.Values, error) {
		env := rs.Env()
		lineID := rs.IDs()[0]
		var qty, price, discount float64
		env.Tx().QueryRow(env.Ctx(),
			`SELECT COALESCE(product_uom_qty, 0), COALESCE(price_unit, 0), COALESCE(discount, 0)
			 FROM sale_order_template_line WHERE id = $1`, lineID,
		).Scan(&qty, &price, &discount)
		return orm.Values{"price_subtotal": qty * price * (1 - discount/100)}, nil
	})
}

// initSaleOrderTemplateOption registers sale.order.template.option.
// Mirrors: odoo/addons/sale_management/models/sale_order_template.py SaleOrderTemplateOption
func initSaleOrderTemplateOption() {
	m := orm.NewModel("sale.order.template.option", orm.ModelOpts{
		Description: "Quotation Template Option",
		Order:       "sequence, id",
	})

	m.AddFields(
		orm.Many2one("sale_order_template_id", "sale.order.template", orm.FieldOpts{
			String: "Template", Required: true, OnDelete: orm.OnDeleteCascade, Index: true,
		}),
		orm.Many2one("product_id", "product.product", orm.FieldOpts{String: "Product", Required: true}),
		orm.Char("name", orm.FieldOpts{String: "Description", Required: true, Translate: true}),
		orm.Float("quantity", orm.FieldOpts{String: "Quantity", Default: 1}),
		orm.Many2one("uom_id", "uom.uom", orm.FieldOpts{String: "Unit of Measure"}),
		orm.Float("price_unit", orm.FieldOpts{String: "Unit Price"}),
		orm.Float("discount", orm.FieldOpts{String: "Discount (%)"}),
		orm.Integer("sequence", orm.FieldOpts{String: "Sequence", Default: 10}),
	)

	// Onchange: product_id → name + price_unit
	m.RegisterOnchange("product_id", func(env *orm.Environment, vals orm.Values) orm.Values {
		result := make(orm.Values)

		var productID int64
		switch v := vals["product_id"].(type) {
		case int64:
			productID = v
		case float64:
			productID = int64(v)
		case map[string]interface{}:
			if id, ok := v["id"]; ok {
				switch n := id.(type) {
				case float64:
					productID = int64(n)
				case int64:
					productID = n
				}
			}
		}
		if productID <= 0 {
			return result
		}

		var name string
		var listPrice float64
		err := env.Tx().QueryRow(env.Ctx(),
			`SELECT COALESCE(pt.name, ''), COALESCE(pt.list_price, 0)
			 FROM product_product pp
			 JOIN product_template pt ON pt.id = pp.product_tmpl_id
			 WHERE pp.id = $1`, productID,
		).Scan(&name, &listPrice)
		if err != nil {
			return result
		}

		result["name"] = name
		result["price_unit"] = listPrice
		return result
	})
}
