package repository

import (
	"fmt"

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

type MarketingDeliveryAttributionRow struct {
	MarketingDeliveryProductID uint    `gorm:"column:marketing_delivery_product_id"`
	ProjectFlockKandangID      uint    `gorm:"column:project_flock_kandang_id"`
	ProjectFlockID             uint    `gorm:"column:project_flock_id"`
	ProjectFlockCategory       string  `gorm:"column:project_flock_category"`
	AllocatedQty               float64 `gorm:"column:allocated_qty"`
}

func MarketingDeliveryAttributionRowsQuery(db *gorm.DB) *gorm.DB {
	sql := `
WITH mapped AS (
	SELECT
		sa.usable_id AS marketing_delivery_product_id,
		pc.project_flock_kandang_id AS project_flock_kandang_id,
		pfk.project_flock_id AS project_flock_id,
		pf.category AS project_flock_category,
		SUM(sa.qty) AS allocated_qty
	FROM stock_allocations sa
	JOIN project_flock_populations pfp
		ON pfp.id = sa.stockable_id
		AND sa.stockable_type = ?
	JOIN project_chickins pc ON pc.id = pfp.project_chickin_id
	JOIN project_flock_kandangs pfk ON pfk.id = pc.project_flock_kandang_id
	JOIN project_flocks pf ON pf.id = pfk.project_flock_id
	WHERE sa.usable_type = ?
		AND sa.status = ?
		AND sa.allocation_purpose = ?
	GROUP BY sa.usable_id, pc.project_flock_kandang_id, pfk.project_flock_id, pf.category

	UNION ALL

	SELECT
		sa.usable_id AS marketing_delivery_product_id,
		COALESCE(re.project_flock_kandang_id, r.project_flock_kandangs_id) AS project_flock_kandang_id,
		pfk.project_flock_id AS project_flock_id,
		pf.category AS project_flock_category,
		SUM(sa.qty) AS allocated_qty
	FROM stock_allocations sa
	JOIN recording_eggs re
		ON re.id = sa.stockable_id
		AND sa.stockable_type = ?
	LEFT JOIN recordings r ON r.id = re.recording_id
	JOIN project_flock_kandangs pfk ON pfk.id = COALESCE(re.project_flock_kandang_id, r.project_flock_kandangs_id)
	JOIN project_flocks pf ON pf.id = pfk.project_flock_id
	WHERE sa.usable_type = ?
		AND sa.status = ?
		AND sa.allocation_purpose = ?
	GROUP BY sa.usable_id, COALESCE(re.project_flock_kandang_id, r.project_flock_kandangs_id), pfk.project_flock_id, pf.category

	UNION ALL

	SELECT
		sa.usable_id AS marketing_delivery_product_id,
		COALESCE(rd.source_project_flock_kandang_id, r.project_flock_kandangs_id) AS project_flock_kandang_id,
		pfk.project_flock_id AS project_flock_id,
		pf.category AS project_flock_category,
		SUM(sa.qty) AS allocated_qty
	FROM stock_allocations sa
	JOIN recording_depletions rd
		ON rd.id = sa.stockable_id
		AND sa.stockable_type = ?
	LEFT JOIN recordings r ON r.id = rd.recording_id
	JOIN project_flock_kandangs pfk ON pfk.id = COALESCE(rd.source_project_flock_kandang_id, r.project_flock_kandangs_id)
	JOIN project_flocks pf ON pf.id = pfk.project_flock_id
	WHERE sa.usable_type = ?
		AND sa.status = ?
		AND sa.allocation_purpose = ?
	GROUP BY sa.usable_id, COALESCE(rd.source_project_flock_kandang_id, r.project_flock_kandangs_id), pfk.project_flock_id, pf.category

	UNION ALL

	SELECT
		sa.usable_id AS marketing_delivery_product_id,
		pi.project_flock_kandang_id AS project_flock_kandang_id,
		pfk.project_flock_id AS project_flock_id,
		pf.category AS project_flock_category,
		SUM(sa.qty) AS allocated_qty
	FROM stock_allocations sa
	JOIN purchase_items pi
		ON pi.id = sa.stockable_id
		AND sa.stockable_type = ?
	JOIN project_flock_kandangs pfk ON pfk.id = pi.project_flock_kandang_id
	JOIN project_flocks pf ON pf.id = pfk.project_flock_id
	WHERE sa.usable_type = ?
		AND sa.status = ?
		AND sa.allocation_purpose = ?
		AND pi.project_flock_kandang_id IS NOT NULL
	GROUP BY sa.usable_id, pi.project_flock_kandang_id, pfk.project_flock_id, pf.category

	UNION ALL

	SELECT
		sa.usable_id AS marketing_delivery_product_id,
		source_pw.project_flock_kandang_id AS project_flock_kandang_id,
		pfk.project_flock_id AS project_flock_id,
		pf.category AS project_flock_category,
		SUM(sa.qty) AS allocated_qty
	FROM stock_allocations sa
	JOIN stock_transfer_details std
		ON std.id = sa.stockable_id
		AND sa.stockable_type = ?
	JOIN product_warehouses source_pw ON source_pw.id = std.source_product_warehouse_id
	JOIN project_flock_kandangs pfk ON pfk.id = source_pw.project_flock_kandang_id
	JOIN project_flocks pf ON pf.id = pfk.project_flock_id
	WHERE sa.usable_type = ?
		AND sa.status = ?
		AND sa.allocation_purpose = ?
		AND source_pw.project_flock_kandang_id IS NOT NULL
	GROUP BY sa.usable_id, source_pw.project_flock_kandang_id, pfk.project_flock_id, pf.category

	UNION ALL

	SELECT
		sa.usable_id AS marketing_delivery_product_id,
		ltt.target_project_flock_kandang_id AS project_flock_kandang_id,
		pfk.project_flock_id AS project_flock_id,
		pf.category AS project_flock_category,
		SUM(sa.qty) AS allocated_qty
	FROM stock_allocations sa
	JOIN laying_transfer_targets ltt
		ON ltt.id = sa.stockable_id
		AND sa.stockable_type = ?
	JOIN project_flock_kandangs pfk ON pfk.id = ltt.target_project_flock_kandang_id
	JOIN project_flocks pf ON pf.id = pfk.project_flock_id
	WHERE sa.usable_type = ?
		AND sa.status = ?
		AND sa.allocation_purpose = ?
	GROUP BY sa.usable_id, ltt.target_project_flock_kandang_id, pfk.project_flock_id, pf.category
)
SELECT
	src.marketing_delivery_product_id,
	src.project_flock_kandang_id,
	src.project_flock_id,
	src.project_flock_category,
	SUM(src.allocated_qty) AS allocated_qty
FROM (
	SELECT
		mapped.marketing_delivery_product_id,
		mapped.project_flock_kandang_id,
		mapped.project_flock_id,
		mapped.project_flock_category,
		mapped.allocated_qty
	FROM mapped

	UNION ALL

	SELECT
		mdp.id AS marketing_delivery_product_id,
		pw.project_flock_kandang_id AS project_flock_kandang_id,
		pfk.project_flock_id AS project_flock_id,
		pf.category AS project_flock_category,
		COALESCE(mdp.usage_qty, 0) AS allocated_qty
	FROM marketing_delivery_products mdp
	JOIN marketing_products mp ON mp.id = mdp.marketing_product_id
	JOIN product_warehouses pw ON pw.id = mp.product_warehouse_id
	JOIN project_flock_kandangs pfk ON pfk.id = pw.project_flock_kandang_id
	JOIN project_flocks pf ON pf.id = pfk.project_flock_id
	LEFT JOIN mapped ON mapped.marketing_delivery_product_id = mdp.id
	WHERE mapped.marketing_delivery_product_id IS NULL
		AND pw.project_flock_kandang_id IS NOT NULL
		AND COALESCE(mdp.usage_qty, 0) > 0
) src
GROUP BY
	src.marketing_delivery_product_id,
	src.project_flock_kandang_id,
	src.project_flock_id,
	src.project_flock_category
`

	return db.Raw(
		sql,
		fifo.StockableKeyProjectFlockPopulation.String(),
		fifo.UsableKeyMarketingDelivery.String(),
		entity.StockAllocationStatusActive,
		entity.StockAllocationPurposeConsume,
		fifo.StockableKeyRecordingEgg.String(),
		fifo.UsableKeyMarketingDelivery.String(),
		entity.StockAllocationStatusActive,
		entity.StockAllocationPurposeConsume,
		fifo.StockableKeyRecordingDepletion.String(),
		fifo.UsableKeyMarketingDelivery.String(),
		entity.StockAllocationStatusActive,
		entity.StockAllocationPurposeConsume,
		fifo.StockableKeyPurchaseItems.String(),
		fifo.UsableKeyMarketingDelivery.String(),
		entity.StockAllocationStatusActive,
		entity.StockAllocationPurposeConsume,
		fifo.StockableKeyStockTransferIn.String(),
		fifo.UsableKeyMarketingDelivery.String(),
		entity.StockAllocationStatusActive,
		entity.StockAllocationPurposeConsume,
		fifo.StockableKeyTransferToLayingIn.String(),
		fifo.UsableKeyMarketingDelivery.String(),
		entity.StockAllocationStatusActive,
		entity.StockAllocationPurposeConsume,
	)
}

func MarketingDeliverySingleAttributionQuery(db *gorm.DB) *gorm.DB {
	return db.
		Table("(?) AS mda", MarketingDeliveryAttributionRowsQuery(db)).
		Select(`
			mda.marketing_delivery_product_id,
			CASE
				WHEN COUNT(DISTINCT mda.project_flock_kandang_id) = 1 THEN MIN(mda.project_flock_kandang_id)
				ELSE NULL
			END AS attributed_project_flock_kandang_id
		`).
		Group("mda.marketing_delivery_product_id")
}

func MarketingDeliveryAttributionFilterSQL(column string) string {
	return fmt.Sprintf("EXISTS (SELECT 1 FROM (?) AS mda WHERE mda.marketing_delivery_product_id = %s)", column)
}
