package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"math"
	"os"

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

type mismatchRow struct {
	ChickinID           uint    `gorm:"column:chickin_id"`
	ProjectFlockKandang uint    `gorm:"column:project_flock_kandang_id"`
	ProductWarehouseID  uint    `gorm:"column:product_warehouse_id"`
	UsageQty            float64 `gorm:"column:usage_qty"`
	TraceQty            float64 `gorm:"column:trace_qty"`
}

func main() {
	var projectFlockKandangID uint
	flag.UintVar(&projectFlockKandangID, "project-flock-kandang-id", 0, "Optional project flock kandang scope")
	flag.Parse()

	ctx := context.Background()
	db := database.Connect(config.DBHost, config.DBName)

	rows, err := loadTraceMismatches(ctx, db, projectFlockKandangID)
	if err != nil {
		log.Fatalf("failed to load trace mismatches: %v", err)
	}

	activeConsumeRows, err := countActiveConsumeProjectChickin(ctx, db, projectFlockKandangID)
	if err != nil {
		log.Fatalf("failed to count active consume rows: %v", err)
	}

	fmt.Printf("Scope project_flock_kandang_id=%d\n", projectFlockKandangID)
	fmt.Printf("Mismatched chickin trace rows: %d\n", len(rows))
	fmt.Printf("Active PROJECT_CHICKIN consume rows: %d\n", activeConsumeRows)

	if len(rows) > 0 {
		for _, row := range rows {
			fmt.Printf(
				"MISMATCH chickin_id=%d pfk=%d pw=%d usage=%.3f trace=%.3f diff=%.3f\n",
				row.ChickinID,
				row.ProjectFlockKandang,
				row.ProductWarehouseID,
				row.UsageQty,
				row.TraceQty,
				row.TraceQty-row.UsageQty,
			)
		}
	}

	if len(rows) > 0 || activeConsumeRows > 0 {
		os.Exit(1)
	}
}

func loadTraceMismatches(ctx context.Context, db *gorm.DB, projectFlockKandangID uint) ([]mismatchRow, error) {
	query := db.WithContext(ctx).
		Table("project_chickins pc").
		Select(`
			pc.id AS chickin_id,
			pc.project_flock_kandang_id,
			pc.product_warehouse_id,
			COALESCE(pc.usage_qty, 0) AS usage_qty,
			COALESCE(SUM(sa.qty), 0) AS trace_qty
		`).
		Joins(`
			LEFT JOIN stock_allocations sa
				ON sa.usable_type = ?
				AND sa.usable_id = pc.id
				AND sa.status = 'ACTIVE'
				AND sa.allocation_purpose = 'TRACE_CHICKIN'
		`, fifo.UsableKeyProjectChickin.String()).
		Where("pc.deleted_at IS NULL").
		Where("COALESCE(pc.usage_qty,0) > 0").
		Group("pc.id, pc.project_flock_kandang_id, pc.product_warehouse_id, pc.usage_qty")

	if projectFlockKandangID > 0 {
		query = query.Where("pc.project_flock_kandang_id = ?", projectFlockKandangID)
	}

	rows := make([]mismatchRow, 0)
	if err := query.Scan(&rows).Error; err != nil {
		return nil, err
	}

	out := make([]mismatchRow, 0, len(rows))
	for _, row := range rows {
		if math.Abs(row.TraceQty-row.UsageQty) > 1e-3 {
			out = append(out, row)
		}
	}
	return out, nil
}

func countActiveConsumeProjectChickin(ctx context.Context, db *gorm.DB, projectFlockKandangID uint) (int64, error) {
	q := db.WithContext(ctx).
		Table("stock_allocations sa").
		Joins("JOIN project_chickins pc ON pc.id = sa.usable_id").
		Where("sa.usable_type = ?", fifo.UsableKeyProjectChickin.String()).
		Where("sa.status = 'ACTIVE'").
		Where("sa.allocation_purpose = 'CONSUME'")

	if projectFlockKandangID > 0 {
		q = q.Where("pc.project_flock_kandang_id = ?", projectFlockKandangID)
	}

	var count int64
	if err := q.Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}
