package services

import (
	"time"

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

// CalculatedDeadline is one computed deadline (rule + due date + adjustment info).
type CalculatedDeadline struct {
	RuleCode        string `json:"rule_code"`
	RuleID          string `json:"rule_id"`
	Title           string `json:"title"`
	DueDate         string `json:"due_date"`          // YYYY-MM-DD, after holiday/weekend adjust
	OriginalDueDate string `json:"original_due_date"` // YYYY-MM-DD, before adjust
	WasAdjusted     bool   `json:"was_adjusted"`
}

// DeadlineCalculator turns rules into dates given a trigger event.
type DeadlineCalculator struct {
	holidays *HolidayService
}

// NewDeadlineCalculator wires the calculator to the holiday service.
func NewDeadlineCalculator(holidays *HolidayService) *DeadlineCalculator {
	return &DeadlineCalculator{holidays: holidays}
}

// CalculateEndDate applies a single rule's duration + timing to the event date,
// then bumps forward off non-working days for the given (country, regime).
// Returns (adjusted, original, didAdjust).
func (c *DeadlineCalculator) CalculateEndDate(eventDate time.Time, rule models.DeadlineRule, country, regime string) (time.Time, time.Time, bool) {
	endDate := eventDate

	timing := "after"
	if rule.Timing != nil {
		timing = *rule.Timing
	}

	sign := 1
	if timing == "before" {
		sign = -1
	}

	switch rule.DurationUnit {
	case "days":
		endDate = endDate.AddDate(0, 0, sign*rule.DurationValue)
	case "weeks":
		endDate = endDate.AddDate(0, 0, sign*rule.DurationValue*7)
	case "months":
		endDate = endDate.AddDate(0, sign*rule.DurationValue, 0)
	}

	original := endDate
	adjusted, _, wasAdjusted := c.holidays.AdjustForNonWorkingDays(endDate, country, regime)
	return adjusted, original, wasAdjusted
}

// CalculateFromRules calculates deadlines for a slice of rules using the
// given (country, regime) for non-working-day adjustment. Rules with
// duration == 0 (court-set hearings, decisions) return the event date itself.
func (c *DeadlineCalculator) CalculateFromRules(eventDate time.Time, rules []models.DeadlineRule, country, regime string) []CalculatedDeadline {
	results := make([]CalculatedDeadline, 0, len(rules))
	for _, r := range rules {
		var adjusted, original time.Time
		var wasAdjusted bool

		if r.DurationValue > 0 {
			adjusted, original, wasAdjusted = c.CalculateEndDate(eventDate, r, country, regime)
		} else {
			adjusted, original = eventDate, eventDate
		}

		code := ""
		if r.SubmissionCode != nil {
			code = *r.SubmissionCode
		}

		results = append(results, CalculatedDeadline{
			RuleCode:        code,
			RuleID:          r.ID.String(),
			Title:           r.Name,
			DueDate:         adjusted.Format("2006-01-02"),
			OriginalDueDate: original.Format("2006-01-02"),
			WasAdjusted:     wasAdjusted,
		})
	}
	return results
}
