package dto

import (
	"strings"

	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	"gitlab.com/mbugroup/lti-api.git/internal/utils"
)

type ClosingHPPCode string

const (
	HPPCodePakan      ClosingHPPCode = "PAKAN"
	HPPCodeOVK        ClosingHPPCode = "OVK"
	HPPCodeDOC        ClosingHPPCode = "DOC"
	HPPCodeDepresiasi ClosingHPPCode = "DEPRESIASI"
	HPPCodeOverhead   ClosingHPPCode = "OVERHEAD"
	HPPCodeEkspedisi  ClosingHPPCode = "EKSPEDISI"
)

type ClosingProfitLossCode string

const (
	PLCodeSales     ClosingProfitLossCode = "SALES"
	PLCodeSapronak  ClosingProfitLossCode = "SAPRONAK"
	PLCodeOverhead  ClosingProfitLossCode = "OVERHEAD"
	PLCodeEkspedisi ClosingProfitLossCode = "EKSPEDISI"
)

type FinancialMetrics struct {
	RpPerBird float64 `json:"rp_per_bird"`
	RpPerKg   float64 `json:"rp_per_kg"`
	Amount    float64 `json:"amount"`
}

type HPPItem struct {
	ID          uint             `json:"id"`
	Category    string           `json:"category"`
	Code        string           `json:"code"`
	Label       string           `json:"label"`
	Budgeting   FinancialMetrics `json:"budgeting"`
	Realization FinancialMetrics `json:"realization"`
}

type HPPSummary struct {
	Label          string            `json:"label"`
	Budgeting      FinancialMetrics  `json:"budgeting"`
	Realization    FinancialMetrics  `json:"realization"`
	EggBudgeting   *FinancialMetrics `json:"egg_budgeting,omitempty"`
	EggRealization *FinancialMetrics `json:"egg_realization,omitempty"`
}

type HPPSection struct {
	Items   []HPPItem  `json:"items"`
	Summary HPPSummary `json:"summary"`
}

type ProfitLossItem struct {
	Code      string  `json:"code"`
	Label     string  `json:"label"`
	Type      string  `json:"type"`
	RpPerBird float64 `json:"rp_per_bird"`
	RpPerKg   float64 `json:"rp_per_kg"`
	Amount    float64 `json:"amount"`
}

type ProfitLossSummary struct {
	GrossProfit FinancialMetrics `json:"gross_profit"`
	SubTotal    FinancialMetrics `json:"sub_total"`
	NetProfit   FinancialMetrics `json:"net_profit"`
}

type ProfitLossSection struct {
	Items   []ProfitLossItem  `json:"items"`
	Summary ProfitLossSummary `json:"summary"`
}

type ClosingKeuanganData struct {
	HPP        HPPSection        `json:"hpp"`
	ProfitLoss ProfitLossSection `json:"profit_loss"`
}
type MetricsCalculator struct {
	TotalPopulation     float64
	ActualPopulation    float64
	TotalWeightProduced float64
}

func ToFinancialMetrics(rpPerBird, rpPerKg, amount float64) FinancialMetrics {
	return FinancialMetrics{
		RpPerBird: rpPerBird,
		RpPerKg:   rpPerKg,
		Amount:    amount,
	}
}

func ToHPPItem(id uint, category, code, label string, budgeting, realization FinancialMetrics) HPPItem {
	return HPPItem{
		ID:          id,
		Category:    category,
		Code:        code,
		Label:       label,
		Budgeting:   budgeting,
		Realization: realization,
	}
}

func ToHPPSummary(label string, budgeting, realization FinancialMetrics, eggBudgeting, eggRealization *FinancialMetrics) HPPSummary {
	return HPPSummary{
		Label:          label,
		Budgeting:      budgeting,
		Realization:    realization,
		EggBudgeting:   eggBudgeting,
		EggRealization: eggRealization,
	}
}

func ToHPPSection(items []HPPItem, summary HPPSummary) HPPSection {
	return HPPSection{
		Items:   items,
		Summary: summary,
	}
}

func ToProfitLossItem(code, label, itemType string, rpPerBird, rpPerKg, amount float64) ProfitLossItem {
	return ProfitLossItem{
		Code:      code,
		Label:     label,
		Type:      itemType,
		RpPerBird: rpPerBird,
		RpPerKg:   rpPerKg,
		Amount:    amount,
	}
}

func ToProfitLossSummary(grossProfit, subTotal, netProfit FinancialMetrics) ProfitLossSummary {
	return ProfitLossSummary{
		GrossProfit: grossProfit,
		SubTotal:    subTotal,
		NetProfit:   netProfit,
	}
}

func ToProfitLossSection(items []ProfitLossItem, summary ProfitLossSummary) ProfitLossSection {
	return ProfitLossSection{
		Items:   items,
		Summary: summary,
	}
}

func ToClosingKeuanganData(hpp HPPSection, profitLoss ProfitLossSection) ClosingKeuanganData {
	return ClosingKeuanganData{
		HPP:        hpp,
		ProfitLoss: profitLoss,
	}
}

func (mc *MetricsCalculator) CalculateMetrics(amount float64) (rpPerBird, rpPerKg float64) {
	if mc.ActualPopulation > 0 {
		rpPerBird = amount / mc.ActualPopulation
	}
	if mc.TotalWeightProduced > 0 {
		rpPerKg = amount / mc.TotalWeightProduced
	}
	return
}

func (mc *MetricsCalculator) CalculateProfitLossMetrics(amount float64) (rpPerBird, rpPerKg float64) {
	if mc.TotalPopulation > 0 {
		rpPerBird = amount / mc.TotalPopulation
	}
	if mc.TotalWeightProduced > 0 {
		rpPerKg = amount / mc.TotalWeightProduced
	}
	return
}

type ProductFilter struct {
	ProjectFlockCategory string
}

func (pf *ProductFilter) IsEggProduct(product entity.Product) bool {
	for _, flag := range product.Flags {
		flagName := strings.ToUpper(flag.Name)
		if flagName == string(utils.FlagTelur) ||
			flagName == string(utils.FlagTelurUtuh) ||
			flagName == string(utils.FlagTelurPecah) ||
			flagName == string(utils.FlagTelurPutih) ||
			flagName == string(utils.FlagTelurRetak) {
			return true
		}
	}
	return false
}

func (pf *ProductFilter) IsChickenProduct(product entity.Product) bool {
	for _, flag := range product.Flags {
		flagName := strings.ToUpper(flag.Name)
		if flagName == string(utils.FlagAyamAfkir) ||
			flagName == string(utils.FlagAyamCulling) ||
			flagName == string(utils.FlagAyamMati) {
			return true
		}
	}
	return false
}

func (pf *ProductFilter) ShouldIncludeProduct(product entity.Product) bool {
	if pf.ProjectFlockCategory == string(utils.ProjectFlockCategoryLaying) {
		return pf.IsEggProduct(product)
	}
	return pf.IsChickenProduct(product) || (!pf.IsEggProduct(product) && !pf.IsChickenProduct(product))
}

func (pf *ProductFilter) FilterDeliveryProducts(deliveries []entity.MarketingDeliveryProduct) []entity.MarketingDeliveryProduct {
	filtered := make([]entity.MarketingDeliveryProduct, 0)
	for _, delivery := range deliveries {
		if delivery.MarketingProduct.ProductWarehouse.Product.Id == 0 {
			continue
		}
		if pf.ShouldIncludeProduct(delivery.MarketingProduct.ProductWarehouse.Product) {
			filtered = append(filtered, delivery)
		}
	}
	return filtered
}
