package handlers

import (
	"encoding/json"
	"net/http"
	"time"

	"mgit.msbls.de/m/KanzlAI-mGMT/internal/models"
	"mgit.msbls.de/m/KanzlAI-mGMT/internal/services"
)

// CalculateHandlers holds handlers for deadline calculation endpoints
type CalculateHandlers struct {
	calculator *services.DeadlineCalculator
	rules      *services.DeadlineRuleService
}

// NewCalculateHandlers creates calculate handlers
func NewCalculateHandlers(calc *services.DeadlineCalculator, rules *services.DeadlineRuleService) *CalculateHandlers {
	return &CalculateHandlers{calculator: calc, rules: rules}
}

// CalculateRequest is the input for POST /api/deadlines/calculate
type CalculateRequest struct {
	ProceedingType   string   `json:"proceeding_type"`
	TriggerEventDate string   `json:"trigger_event_date"`
	SelectedRuleIDs  []string `json:"selected_rule_ids,omitempty"`
}

// Calculate handles POST /api/deadlines/calculate
func (h *CalculateHandlers) Calculate(w http.ResponseWriter, r *http.Request) {
	var req CalculateRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		writeError(w, http.StatusBadRequest, "invalid request body")
		return
	}

	if req.ProceedingType == "" || req.TriggerEventDate == "" {
		writeError(w, http.StatusBadRequest, "proceeding_type and trigger_event_date are required")
		return
	}

	eventDate, err := time.Parse("2006-01-02", req.TriggerEventDate)
	if err != nil {
		writeError(w, http.StatusBadRequest, "invalid trigger_event_date format, expected YYYY-MM-DD")
		return
	}

	var results []services.CalculatedDeadline

	if len(req.SelectedRuleIDs) > 0 {
		ruleModels, err := h.rules.GetByIDs(req.SelectedRuleIDs)
		if err != nil {
			writeError(w, http.StatusInternalServerError, "failed to fetch selected rules")
			return
		}
		results = h.calculator.CalculateFromRules(eventDate, ruleModels)
	} else {
		tree, err := h.rules.GetRuleTree(req.ProceedingType)
		if err != nil {
			writeError(w, http.StatusBadRequest, "unknown proceeding type")
			return
		}
		// Flatten tree to get all rule models
		var flatNodes []services.RuleTreeNode
		flattenTree(tree, &flatNodes)

		ruleModels := make([]models.DeadlineRule, 0, len(flatNodes))
		for _, node := range flatNodes {
			ruleModels = append(ruleModels, node.DeadlineRule)
		}
		results = h.calculator.CalculateFromRules(eventDate, ruleModels)
	}

	writeJSON(w, http.StatusOK, map[string]any{
		"proceeding_type":    req.ProceedingType,
		"trigger_event_date": req.TriggerEventDate,
		"deadlines":          results,
	})
}

func flattenTree(nodes []services.RuleTreeNode, result *[]services.RuleTreeNode) {
	for _, n := range nodes {
		*result = append(*result, n)
		if len(n.Children) > 0 {
			flattenTree(n.Children, result)
		}
	}
}
