package repositories

import (
	"context"

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

	"gorm.io/gorm"
)

type ProductionResultRepository interface {
	GetRecordingsByProjectFlockKandang(ctx context.Context, projectFlockKandangID uint, offset, limit int) ([]entity.Recording, int64, error)
	GetProductionStandardIDByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (uint, error)
}

type productionResultRepositoryImpl struct {
	db *gorm.DB
}

func NewProductionResultRepository(db *gorm.DB) ProductionResultRepository {
	return &productionResultRepositoryImpl{db: db}
}

func (r *productionResultRepositoryImpl) GetRecordingsByProjectFlockKandang(
	ctx context.Context,
	projectFlockKandangID uint,
	offset, limit int,
) ([]entity.Recording, int64, error) {
	if projectFlockKandangID == 0 {
		return []entity.Recording{}, 0, nil
	}

	latestApproval := r.db.WithContext(ctx).
		Table("approvals AS a").
		Select("a.approvable_id, a.action, a.step_number").
		Joins(`
			JOIN (
				SELECT approvable_id, MAX(action_at) AS latest_action_at
				FROM approvals
				WHERE approvable_type = ?
				GROUP BY approvable_id
			) AS la ON la.approvable_id = a.approvable_id AND la.latest_action_at = a.action_at`,
			string(utils.ApprovalWorkflowRecording),
		)

	countQuery := r.db.WithContext(ctx).
		Model(&entity.Recording{}).
		Joins("JOIN (?) AS la ON la.approvable_id = recordings.id", latestApproval).
		Where("project_flock_kandangs_id = ?", projectFlockKandangID).
		Where("la.step_number = ?", utils.RecordingStepDisetujui).
		Where("la.action = ?", string(entity.ApprovalActionApproved))

	var total int64
	if err := countQuery.Count(&total).Error; err != nil {
		return nil, 0, err
	}
	if total == 0 {
		return []entity.Recording{}, 0, nil
	}

	if limit <= 0 {
		limit = 10
	}
	if offset < 0 {
		offset = 0
	}

	flagNames := []string{
		string(utils.FlagTelurUtuh),
		string(utils.FlagTelurPutih),
		string(utils.FlagTelurRetak),
		string(utils.FlagTelurPecah),
	}

	dataQuery := r.db.WithContext(ctx).
		Model(&entity.Recording{}).
		Joins("JOIN (?) AS la ON la.approvable_id = recordings.id", latestApproval).
		Where("project_flock_kandangs_id = ?", projectFlockKandangID).
		Where("la.step_number = ?", utils.RecordingStepDisetujui).
		Where("la.action = ?", string(entity.ApprovalActionApproved)).
		Preload("Eggs", func(db *gorm.DB) *gorm.DB {
			return db.Select("recording_eggs.*, f.name AS product_flag_name").
				Joins("LEFT JOIN product_warehouses pw ON pw.id = recording_eggs.product_warehouse_id").
				Joins("LEFT JOIN flags f ON f.flagable_id = pw.product_id AND f.flagable_type = ? AND f.name IN ?", entity.FlagableTypeProduct, flagNames)
		}).
		Preload("Eggs.ProductWarehouse").
		Order("record_datetime ASC").
		Offset(offset).
		Limit(limit)

	var recordings []entity.Recording
	if err := dataQuery.Find(&recordings).Error; err != nil {
		return nil, 0, err
	}

	return recordings, total, nil
}

func (r *productionResultRepositoryImpl) GetProductionStandardIDByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (uint, error) {
	if projectFlockKandangID == 0 {
		return 0, nil
	}

	var row struct {
		ProductionStandardID uint `gorm:"column:production_standard_id"`
	}

	err := r.db.WithContext(ctx).
		Table("project_flock_kandangs pfk").
		Select("pf.production_standard_id").
		Joins("JOIN project_flocks pf ON pf.id = pfk.project_flock_id").
		Where("pfk.id = ?", projectFlockKandangID).
		Take(&row).Error
	if err != nil {
		return 0, err
	}

	return row.ProductionStandardID, nil
}
