package handlers

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

	"mgit.msbls.de/m/paliad/internal/services"
)

// GET /api/deadline-rules?proceeding_type_id=N
//
// Lists deadline rules from the DB, optionally filtered by proceeding type.
// Returns 503 if the DB is not configured.
func handleListDeadlineRules(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	var ptIDPtr *int
	if raw := r.URL.Query().Get("proceeding_type_id"); raw != "" {
		ptID, err := strconv.Atoi(raw)
		if err != nil {
			writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid proceeding_type_id"})
			return
		}
		ptIDPtr = &ptID
	}
	rules, err := dbSvc.rules.List(r.Context(), ptIDPtr)
	if err != nil {
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to list rules"})
		return
	}
	writeJSON(w, http.StatusOK, rules)
}

// GET /api/proceeding-types-db?category=<value>
//
// Lists active proceeding types from the DB. Optional `category` query
// param filters the result set (e.g. ?category=fristenrechner is the
// shape the project-create / project-edit pickers use after Phase 3
// Slice 5 — design §3.F + m's Q2 ruling restricts project-binding to
// fristenrechner-category codes). Empty / missing param returns every
// active row.
//
// (Distinct route name from the existing in-memory /api/tools/proceeding-types
// endpoint to avoid path conflicts during the Phase B → Phase C transition.)
func handleListProceedingTypesDB(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	category := r.URL.Query().Get("category")
	types, err := dbSvc.rules.ListProceedingTypesByCategory(r.Context(), category)
	if err != nil {
		writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "failed to list proceeding types"})
		return
	}
	writeJSON(w, http.StatusOK, types)
}

// POST /api/deadlines/calculate
//
// Body: { "proceeding_type": "INF", "trigger_date": "2026-04-15" }
// Calculates all deadlines for the proceeding type's rule tree, applying
// holiday/weekend adjustment via the DB-backed HolidayService.
//
// Lives at /api/deadlines/calculate (vs the existing /api/tools/fristenrechner
// which uses the in-memory rule tree). Phase C swaps the Fristenrechner UI
// to this endpoint, then deletes the in-memory rule tree.
func handleCalculateDeadlines(w http.ResponseWriter, r *http.Request) {
	if !requireDB(w) {
		return
	}
	var input struct {
		ProceedingType string `json:"proceeding_type"`
		TriggerDate    string `json:"trigger_date"`
		CourtID        string `json:"court_id"`
	}
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON"})
		return
	}
	if input.ProceedingType == "" || input.TriggerDate == "" {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "proceeding_type and trigger_date required"})
		return
	}
	triggerDate, err := time.Parse("2006-01-02", input.TriggerDate)
	if err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "trigger_date must be YYYY-MM-DD"})
		return
	}

	rules, pt, err := dbSvc.rules.GetFullTimeline(r.Context(), input.ProceedingType)
	if err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "unknown proceeding type"})
		return
	}

	defaultCountry, defaultRegime := services.DefaultsForJurisdiction(pt.Jurisdiction)
	country, regime, err := dbSvc.courts.CountryRegime(input.CourtID, defaultCountry, defaultRegime)
	if err != nil {
		writeJSON(w, http.StatusBadRequest, map[string]string{"error": "unknown court_id"})
		return
	}

	results := dbSvc.calc.CalculateFromRules(triggerDate, rules, country, regime)
	writeJSON(w, http.StatusOK, map[string]any{
		"proceeding_type": pt.Code,
		"proceeding_name": pt.Name,
		"trigger_date":    input.TriggerDate,
		"deadlines":       results,
	})
}
