package dto

import (
	"time"

	entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
	productCategoryDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/product-categories/dto"
	uomDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/uoms/dto"
	userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
)

// === DTO Structs ===

type ProductRelationDTO struct {
	Id              uint                                           `json:"id"`
	Name            string                                         `json:"name"`
	SKU             string                                         `json:"sku"`
	Uom             *uomDTO.UomRelationDTO                         `json:"uom,omitempty"`
	ProductCategory *productCategoryDTO.ProductCategoryRelationDTO `json:"product_category,omitempty"`
}

type LocationRelationDTO struct {
	Id   uint   `json:"id"`
	Name string `json:"name"`
}

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

type WarehouseRelationDTO struct {
	Id       uint                 `json:"id"`
	Name     string               `json:"name"`
	Location *LocationRelationDTO `json:"location,omitempty"`
}

type ProductWarehouseDTO struct {
	Id           uint                     `json:"id"`
	ProductId    uint                     `json:"product_id"`
	WarehouseId  uint                     `json:"warehouse_id"`
	Quantity     float64                  `json:"quantity"`
	Product      *ProductRelationDTO      `json:"product,omitempty"`
	Warehouse    *WarehouseRelationDTO    `json:"warehouse,omitempty"`
	ProjectFlock *ProjectFlockRelationDTO `json:"project_flock,omitempty"`
}

type AdjustmentRelationDTO struct {
	Id                 uint                     `json:"id"`
	AdjNumber          string                   `json:"adj_number"`
	TransactionType    string                   `json:"transaction_type"`
	TransactionSubtype string                   `json:"transaction_subtype"`
	FunctionCode       string                   `json:"function_code"`
	Qty                float64                  `json:"qty"`
	Price              float64                  `json:"price"`
	GrandTotal         float64                  `json:"grand_total"`
	Increase           float64                  `json:"increase"`
	Decrease           float64                  `json:"decrease"`
	Notes              string                   `json:"notes,omitempty"`
	Location           *LocationRelationDTO     `json:"location,omitempty"`
	ProjectFlock       *ProjectFlockRelationDTO `json:"project_flock,omitempty"`
	ProductWarehouseId uint                     `json:"product_warehouse_id"`
	ProductWarehouse   *ProductWarehouseDTO     `json:"product_warehouse,omitempty"`
}

type AdjustmentListDTO struct {
	AdjustmentRelationDTO
	CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
	CreatedAt   time.Time                `json:"created_at"`
}

type AdjustmentDetailDTO struct {
	AdjustmentListDTO
	UpdatedAt time.Time `json:"updated_at"`
}

// === Mapper Functions ===

func ToProductRelationDTO(e *entity.Product) *ProductRelationDTO {
	if e == nil {
		return nil
	}
	sku := ""
	if e.Sku != nil {
		sku = *e.Sku
	}

	var category *productCategoryDTO.ProductCategoryRelationDTO
	if e.ProductCategory.Id != 0 {
		mapped := productCategoryDTO.ToProductCategoryRelationDTO(e.ProductCategory)
		category = &mapped
	}
	var uom *uomDTO.UomRelationDTO
	if e.Uom.Id != 0 {
		mapped := uomDTO.ToUomRelationDTO(e.Uom)
		uom = &mapped
	}

	return &ProductRelationDTO{
		Id:              e.Id,
		Name:            e.Name,
		SKU:             sku,
		Uom:             uom,
		ProductCategory: category,
	}
}

func ToWarehouseRelationDTO(e *entity.Warehouse) *WarehouseRelationDTO {
	if e == nil {
		return nil
	}
	return &WarehouseRelationDTO{
		Id:       e.Id,
		Name:     e.Name,
		Location: ToLocationRelationDTO(e.Location),
	}
}

func ToLocationRelationDTO(e *entity.Location) *LocationRelationDTO {
	if e == nil {
		return nil
	}
	return &LocationRelationDTO{
		Id:   e.Id,
		Name: e.Name,
	}
}

func ToProjectFlockRelationDTO(e *entity.ProjectFlockKandang) *ProjectFlockRelationDTO {
	if e == nil || e.ProjectFlock.Id == 0 {
		return nil
	}
	return &ProjectFlockRelationDTO{
		Id:        e.ProjectFlock.Id,
		FlockName: e.ProjectFlock.FlockName,
		Period:    e.Period,
	}
}

func ToProductWarehouseDTO(e *entity.ProductWarehouse) *ProductWarehouseDTO {
	if e == nil {
		return nil
	}
	return &ProductWarehouseDTO{
		Id:           e.Id,
		ProductId:    e.ProductId,
		WarehouseId:  e.WarehouseId,
		Quantity:     e.Quantity,
		Product:      ToProductRelationDTO(&e.Product),
		Warehouse:    ToWarehouseRelationDTO(&e.Warehouse),
		ProjectFlock: ToProjectFlockRelationDTO(e.ProjectFlockKandang),
	}
}

func ToAdjustmentRelationDTO(e *entity.AdjustmentStock) AdjustmentRelationDTO {
	note := ""
	if e.StockLog != nil {
		note = e.StockLog.Notes
	}

	qty := e.TotalQty
	if qty <= 0 {
		qty = e.UsageQty + e.PendingQty
	}

	var location *LocationRelationDTO
	var projectFlock *ProjectFlockRelationDTO
	if e.ProductWarehouse != nil {
		location = ToLocationRelationDTO(e.ProductWarehouse.Warehouse.Location)
		projectFlock = ToProjectFlockRelationDTO(e.ProductWarehouse.ProjectFlockKandang)
	}

	return AdjustmentRelationDTO{
		Id:                 e.Id,
		AdjNumber:          e.AdjNumber,
		TransactionType:    e.TransactionType,
		TransactionSubtype: e.FunctionCode,
		FunctionCode:       e.FunctionCode,
		Qty:                qty,
		Price:              e.Price,
		GrandTotal:         e.GrandTotal,
		Increase:           e.TotalQty,
		Decrease:           e.UsageQty,
		Notes:              note,
		Location:           location,
		ProjectFlock:       projectFlock,
		ProductWarehouseId: e.ProductWarehouseId,
		ProductWarehouse:   ToProductWarehouseDTO(e.ProductWarehouse),
	}
}

func ToAdjustmentListDTO(e *entity.AdjustmentStock) AdjustmentListDTO {
	var createdUser *userDTO.UserRelationDTO

	// Get created user from StockLog
	if e.StockLog != nil && e.StockLog.CreatedUser != nil {
		mapped := userDTO.ToUserRelationDTO(*e.StockLog.CreatedUser)
		createdUser = &mapped
	}

	return AdjustmentListDTO{
		AdjustmentRelationDTO: ToAdjustmentRelationDTO(e),
		CreatedUser:           createdUser,
		CreatedAt:             e.CreatedAt,
	}
}

func ToAdjustmentDetailDTO(e *entity.AdjustmentStock) AdjustmentDetailDTO {
	return AdjustmentDetailDTO{
		AdjustmentListDTO: ToAdjustmentListDTO(e),
	}
}
