package orm

import (
	"fmt"
	"log"
)

// SetupAllInherits generates Related fields for all models with _inherits declarations.
// Must be called after all models are registered but before computes are set up.
// Mirrors: odoo/orm/model_classes.py _add_inherited_fields()
func SetupAllInherits() {
	for _, m := range Registry.Models() {
		if len(m.inherits) == 0 {
			continue
		}
		setupModelInherits(m)
	}
}

func setupModelInherits(m *Model) {
	for parentName, fkField := range m.inherits {
		parent := Registry.Get(parentName)
		if parent == nil {
			log.Printf("inherits: parent model %q not found for %s", parentName, m.Name())
			continue
		}

		// Verify FK field exists on child
		fkDef := m.GetField(fkField)
		if fkDef == nil {
			log.Printf("inherits: FK field %q not found on %s", fkField, m.Name())
			continue
		}

		// For each parent field, create a Related field on child if not already defined
		inherited := 0
		for _, fname := range parent.fieldOrder {
			// Skip magic fields (child has its own)
			if fname == "id" || fname == "display_name" ||
				fname == "create_uid" || fname == "create_date" ||
				fname == "write_uid" || fname == "write_date" {
				continue
			}

			// Don't override fields already defined on child
			if existing := m.GetField(fname); existing != nil {
				continue
			}

			pf := parent.GetField(fname)
			if pf == nil {
				continue
			}

			// Create Related field: "fk_field.field_name"
			relatedPath := fkField + "." + fname

			inheritedField := &Field{
				Name:          fname,
				Type:          pf.Type,
				String:        pf.String,
				Help:          pf.Help,
				Related:       relatedPath,
				Comodel:       pf.Comodel,
				InverseField:  pf.InverseField,
				Selection:     pf.Selection,
				CurrencyField: pf.CurrencyField,
				Readonly:      pf.Readonly,
				Required:      false, // Inherited fields are not required on child
				model:         m,
				column:        fname,
			}

			// Add to model's field maps
			m.fields[fname] = inheritedField
			m.allFields[fname] = inheritedField
			m.fieldOrder = append(m.fieldOrder, fname)
			inherited++
		}

		log.Printf("inherits: %s inherits %d fields from %s via %s",
			m.Name(), inherited, parentName, fkField)
	}
}

// preprocessInheritsCreate separates inherited field values and creates/updates parent records.
// Must be called in Create() BEFORE ApplyDefaults.
// Mirrors: odoo/orm/models.py create() _inherits handling
func preprocessInheritsCreate(env *Environment, m *Model, vals Values) error {
	if len(m.inherits) == 0 {
		return nil
	}

	for parentName, fkField := range m.inherits {
		parent := Registry.Get(parentName)
		if parent == nil {
			continue
		}

		// Separate parent vals from child vals
		parentVals := make(Values)
		for fieldName, val := range vals {
			// Check if this field belongs to parent (not child's own stored field)
			childField := m.fields[fieldName]
			parentField := parent.GetField(fieldName)

			if parentField != nil && fieldName != fkField &&
				(childField == nil || childField.Related != "") {
				parentVals[fieldName] = val
				delete(vals, fieldName)
			}
		}

		// Check if FK is already provided
		fkVal, hasFk := vals[fkField]
		if hasFk && fkVal != nil {
			// FK provided — update existing parent record with any inherited vals
			fkID := int64(0)
			switch v := fkVal.(type) {
			case float64:
				fkID = int64(v)
			case int64:
				fkID = v
			case int32:
				fkID = int64(v)
			}
			if fkID > 0 && len(parentVals) > 0 {
				parentRS := env.Model(parentName).Browse(fkID)
				if err := parentRS.Write(parentVals); err != nil {
					return fmt.Errorf("inherits: update %s(%d): %w", parentName, fkID, err)
				}
			}
		} else {
			// No FK — create parent record first
			if len(parentVals) == 0 {
				// Need at least something for the parent (e.g., name)
				// Check if name is in child vals but not moved to parent
				if nameVal, ok := vals["name"]; ok {
					parentVals["name"] = nameVal
				}
			}
			parentRS := env.Model(parentName)
			created, err := parentRS.Create(parentVals)
			if err != nil {
				return fmt.Errorf("inherits: create %s: %w", parentName, err)
			}
			vals[fkField] = created.ID()
		}
	}

	return nil
}
