package dto

import (
	"time"

	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto"
	warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
	"gitlab.com/mbugroup/lti-api.git/internal/utils"
)

// === DTO Structs ===

type ProductWarehouseRelationDTO struct {
	Id                   uint     `json:"id"`
	ProductId            uint     `json:"product_id"`
	WarehouseId          uint     `json:"warehouse_id"`
	Quantity             float64  `json:"quantity"`
	TransferAvailableQty *float64 `json:"transfer_available_qty,omitempty"`
}

type ProductWarehouseListDTO struct {
	ProductWarehouseRelationDTO
	Product             *productDTO.ProductRelationDTO     `json:"product,omitempty"`
	Warehouse           *warehouseDTO.WarehouseRelationDTO `json:"warehouse,omitempty"`
	ProjectFlockKandang *ProjectFlockKandangRelationDTO    `json:"project_flock_kandang,omitempty"`
	Week                int                                `json:"week"`
	CreatedUser         *UserRelationDTO                   `json:"created_user,omitempty"`
	CreatedAt           time.Time                          `json:"created_at"`
	UpdatedAt           time.Time                          `json:"updated_at"`
}

type ProductWarehouseDetailDTO struct {
	ProductWarehouseListDTO
}

type ProductWarehousNestedDTO struct {
	Id        uint                               `json:"id"`
	Product   *productDTO.ProductRelationDTO     `json:"product,omitempty"`
	Warehouse *warehouseDTO.WarehouseRelationDTO `json:"warehouse,omitempty"`
}

type UserRelationDTO struct {
	Id       uint   `json:"id"`
	Username string `json:"username"`
}

type ProjectFlockKandangRelationDTO struct {
	Id             uint                     `json:"id"`
	ProjectFlockId uint                     `json:"project_flock_id"`
	KandangId      uint                     `json:"kandang_id"`
	Period         int                      `json:"period"`
	ProjectFlock   *ProjectFlockRelationDTO `json:"project_flock,omitempty"`
}

type ProjectFlockRelationDTO struct {
	Id        uint   `json:"id"`
	FlockName string `json:"flock_name"`
}

// === Mapper Functions ===

func ToProductWarehouseRelationDTO(e entity.ProductWarehouse) ProductWarehouseRelationDTO {
	return ProductWarehouseRelationDTO{
		Id:                   e.Id,
		ProductId:            e.ProductId,   // Field yang benar dari entity
		WarehouseId:          e.WarehouseId, // Field yang benar dari entity
		Quantity:             e.Quantity,
		TransferAvailableQty: e.AvailableQty,
	}
}

func ToProductWarehouseListDTO(e entity.ProductWarehouse) ProductWarehouseListDTO {
	dto := ProductWarehouseListDTO{
		ProductWarehouseRelationDTO: ToProductWarehouseRelationDTO(e),
	}

	// Map Product relation jika ada
	if e.Product.Id != 0 {
		product := productDTO.ToProductRelationDTO(e.Product)

		// Create a copy with flock name appended if exists
		if e.ProjectFlockKandang != nil && e.ProjectFlockKandang.ProjectFlock.Id != 0 {
			productCopy := product
			productCopy.Name = product.Name + " (" + e.ProjectFlockKandang.ProjectFlock.FlockName + ")"
			dto.Product = &productCopy
		} else {
			dto.Product = &product
		}
	}

	// Map Warehouse relation jika ada
	if e.Warehouse.Id != 0 {
		warehouse := warehouseDTO.ToWarehouseRelationDTO(e.Warehouse)

		dto.Warehouse = &warehouse
	}

	// Map ProjectFlockKandang relation jika ada
	if e.ProjectFlockKandang != nil && e.ProjectFlockKandang.Id != 0 {
		pfkDTO := &ProjectFlockKandangRelationDTO{
			Id:             e.ProjectFlockKandang.Id,
			ProjectFlockId: e.ProjectFlockKandang.ProjectFlockId,
			KandangId:      e.ProjectFlockKandang.KandangId,
			Period:         e.ProjectFlockKandang.Period,
		}

		if e.ProjectFlockKandang.ProjectFlock.Id != 0 {
			pfkDTO.ProjectFlock = &ProjectFlockRelationDTO{
				Id:        e.ProjectFlockKandang.ProjectFlock.Id,
				FlockName: e.ProjectFlockKandang.ProjectFlock.FlockName,
			}
		}

		dto.ProjectFlockKandang = pfkDTO

		// Calculate week for AYAM_PULLET/AYAM products
		productFlags := make([]string, len(e.Product.Flags))
		for i, f := range e.Product.Flags {
			productFlags[i] = f.Name
		}

		var category string
		if e.ProjectFlockKandang.ProjectFlock.Id != 0 {
			category = e.ProjectFlockKandang.ProjectFlock.Category
		}

		now := time.Now()
		_, ageInWeeks := calculateAgeFromChickin(e.ProjectFlockKandang, &now, productFlags, category)

		dto.Week = ageInWeeks
	}

	return dto
}

func ToProductWarehouseListDTOs(e []entity.ProductWarehouse) []ProductWarehouseListDTO {
	result := make([]ProductWarehouseListDTO, len(e))
	for i, r := range e {
		result[i] = ToProductWarehouseListDTO(r)
	}
	return result
}

func ToProductWarehouseDetailDTO(e entity.ProductWarehouse) ProductWarehouseDetailDTO {
	return ProductWarehouseDetailDTO{
		ProductWarehouseListDTO: ToProductWarehouseListDTO(e),
	}
}

func ToProductWarehouseNestedDTO(e entity.ProductWarehouse) ProductWarehousNestedDTO {
	product := productDTO.ToProductRelationDTO(e.Product)
	warehouse := warehouseDTO.ToWarehouseRelationDTO(e.Warehouse)

	return ProductWarehousNestedDTO{
		Id:        e.Id,
		Product:   &product,
		Warehouse: &warehouse,
	}
}

// Helper function to calculate age from chickin (same logic as closingMarketing.dto.go)
func calculateAgeFromChickin(projectFlockKandang *entity.ProjectFlockKandang, currentDate *time.Time, productFlags []string, category string) (int, int) {
	if projectFlockKandang == nil || currentDate == nil || len(projectFlockKandang.Chickins) == 0 {
		return 0, 0
	}

	// Return 0 for TRADING, TELUR, and AYAM flags (only AYAM_PULLET should have week)
	for _, flag := range productFlags {
		if flag == string(utils.FlagOVK) ||
			flag == string(utils.FlagPakan) ||
			flag == string(utils.FlagPreStarter) ||
			flag == string(utils.FlagStarter) ||
			flag == string(utils.FlagFinisher) ||
			flag == string(utils.FlagObat) ||
			flag == string(utils.FlagVitamin) ||
			flag == string(utils.FlagKimia) ||
			flag == string(utils.FlagEkspedisi) ||
			flag == string(utils.FlagTelur) ||
			flag == string(utils.FlagTelurUtuh) ||
			flag == string(utils.FlagTelurPecah) ||
			flag == string(utils.FlagTelurPutih) ||
			flag == string(utils.FlagTelurRetak) ||
			flag == string(utils.FlagAyamAfkir) ||
			flag == string(utils.FlagAyamCulling) ||
			flag == string(utils.FlagAyamMati) {
			return 0, 0
		}
	}

	// Find earliest chickin date
	earliestChickinDate := projectFlockKandang.Chickins[0].ChickInDate
	for _, chickin := range projectFlockKandang.Chickins {
		if chickin.ChickInDate.Before(earliestChickinDate) {
			earliestChickinDate = chickin.ChickInDate
		}
	}

	diff := currentDate.Sub(earliestChickinDate)
	ageInDays := int(diff.Hours() / 24)

	var ageInWeeks int
	if ageInDays <= 0 {
		ageInWeeks = 0
	} else {
		if category == string(utils.ProjectFlockCategoryLaying) {
			ageInDays = ageInDays + 119
			ageInWeeks = ((ageInDays - 1) / 7) + 1
		} else {
			ageInWeeks = ((ageInDays - 1) / 7) + 1
		}
	}

	return ageInDays, ageInWeeks
}
