package service

import (
	"strings"
	"time"
)

const (
	depreciationStartAgeDayCloseHouse = 155
	depreciationStartAgeDayOpenHouse  = 176
)

func NormalizeDepreciationHouseType(raw string) string {
	return strings.TrimSpace(strings.ToLower(raw))
}

func DepreciationStartAgeDay(houseType string) int {
	switch NormalizeDepreciationHouseType(houseType) {
	case "close_house":
		return depreciationStartAgeDayCloseHouse
	case "open_house":
		return depreciationStartAgeDayOpenHouse
	default:
		return 0
	}
}

func FlockAgeDay(originDate time.Time, periodDate time.Time) int {
	origin := time.Date(originDate.Year(), originDate.Month(), originDate.Day(), 0, 0, 0, 0, originDate.Location())
	period := time.Date(periodDate.Year(), periodDate.Month(), periodDate.Day(), 0, 0, 0, 0, periodDate.Location())
	if period.Before(origin) {
		return 0
	}
	return int(period.Sub(origin).Hours()/24) + 1
}

func DepreciationScheduleDay(originDate time.Time, periodDate time.Time, houseType string) int {
	ageDay := FlockAgeDay(originDate, periodDate)
	startAgeDay := DepreciationStartAgeDay(houseType)
	if ageDay <= 0 || startAgeDay <= 0 || ageDay < startAgeDay {
		return 0
	}
	return ageDay - startAgeDay + 1
}

func CalculateDepreciationAtDayN(
	initialPulletCost float64,
	dayN int,
	houseType string,
	percentByHouseType map[string]map[int]float64,
) (float64, float64, float64) {
	return CalculateDepreciationFromDayRange(initialPulletCost, 1, dayN, houseType, percentByHouseType)
}

func CalculateDepreciationFromDayRange(
	initialPulletCost float64,
	startDay int,
	endDay int,
	houseType string,
	percentByHouseType map[string]map[int]float64,
) (float64, float64, float64) {
	if initialPulletCost <= 0 || endDay <= 0 {
		return 0, 0, 0
	}
	if startDay <= 0 {
		startDay = 1
	}
	if endDay < startDay {
		return 0, 0, 0
	}

	normalizedHouseType := NormalizeDepreciationHouseType(houseType)
	housePercent, exists := percentByHouseType[normalizedHouseType]
	if !exists {
		return 0, 0, 0
	}

	current := initialPulletCost
	pulletCostDayN := 0.0
	depreciationValue := 0.0
	depreciationPercent := 0.0
	for day := startDay; day <= endDay; day++ {
		pct := housePercent[day]
		dep := current * (pct / 100)
		if day == endDay {
			pulletCostDayN = current
			depreciationValue = dep
			depreciationPercent = pct
		}
		current -= dep
		if current < 0 {
			current = 0
		}
	}

	return pulletCostDayN, depreciationValue, depreciationPercent
}

func CalculateEffectiveDepreciationPercent(totalDepreciationValue, totalPulletCostDayN float64) float64 {
	if totalPulletCostDayN <= 0 {
		return 0
	}
	return (totalDepreciationValue / totalPulletCostDayN) * 100
}
