package postgres

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/store"
	"gorm.io/gorm"
)

type ShopPackageAllocationStore struct {
	db *gorm.DB
}

func NewShopPackageAllocationStore(db *gorm.DB) *ShopPackageAllocationStore {
	return &ShopPackageAllocationStore{db: db}
}

func (s *ShopPackageAllocationStore) Create(ctx context.Context, allocation *model.ShopPackageAllocation) error {
	return s.db.WithContext(ctx).Create(allocation).Error
}

func (s *ShopPackageAllocationStore) GetByID(ctx context.Context, id uint) (*model.ShopPackageAllocation, error) {
	var allocation model.ShopPackageAllocation
	if err := s.db.WithContext(ctx).First(&allocation, id).Error; err != nil {
		return nil, err
	}
	return &allocation, nil
}

func (s *ShopPackageAllocationStore) GetByShopAndPackage(ctx context.Context, shopID, packageID uint) (*model.ShopPackageAllocation, error) {
	var allocation model.ShopPackageAllocation
	if err := s.db.WithContext(ctx).Where("shop_id = ? AND package_id = ?", shopID, packageID).First(&allocation).Error; err != nil {
		return nil, err
	}
	return &allocation, nil
}

func (s *ShopPackageAllocationStore) Update(ctx context.Context, allocation *model.ShopPackageAllocation) error {
	return s.db.WithContext(ctx).Save(allocation).Error
}

func (s *ShopPackageAllocationStore) Delete(ctx context.Context, id uint) error {
	return s.db.WithContext(ctx).Delete(&model.ShopPackageAllocation{}, id).Error
}

func (s *ShopPackageAllocationStore) List(ctx context.Context, opts *store.QueryOptions, filters map[string]interface{}) ([]*model.ShopPackageAllocation, int64, error) {
	var allocations []*model.ShopPackageAllocation
	var total int64

	query := s.db.WithContext(ctx).Model(&model.ShopPackageAllocation{})

	if shopID, ok := filters["shop_id"].(uint); ok && shopID > 0 {
		query = query.Where("shop_id = ?", shopID)
	}
	if packageID, ok := filters["package_id"].(uint); ok && packageID > 0 {
		query = query.Where("package_id = ?", packageID)
	}
	if allocationID, ok := filters["allocation_id"].(uint); ok && allocationID > 0 {
		query = query.Where("allocation_id = ?", allocationID)
	}
	if status, ok := filters["status"].(int); ok && status > 0 {
		query = query.Where("status = ?", status)
	}

	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	if opts == nil {
		opts = store.DefaultQueryOptions()
	}
	offset := (opts.Page - 1) * opts.PageSize
	query = query.Offset(offset).Limit(opts.PageSize)

	if opts.OrderBy != "" {
		query = query.Order(opts.OrderBy)
	}

	if err := query.Find(&allocations).Error; err != nil {
		return nil, 0, err
	}

	return allocations, total, nil
}

func (s *ShopPackageAllocationStore) UpdateStatus(ctx context.Context, id uint, status int, updater uint) error {
	return s.db.WithContext(ctx).
		Model(&model.ShopPackageAllocation{}).
		Where("id = ?", id).
		Updates(map[string]interface{}{
			"status":  status,
			"updater": updater,
		}).Error
}

func (s *ShopPackageAllocationStore) GetByShopID(ctx context.Context, shopID uint) ([]*model.ShopPackageAllocation, error) {
	var allocations []*model.ShopPackageAllocation
	if err := s.db.WithContext(ctx).Where("shop_id = ? AND status = 1", shopID).Find(&allocations).Error; err != nil {
		return nil, err
	}
	return allocations, nil
}

func (s *ShopPackageAllocationStore) DeleteByAllocationID(ctx context.Context, allocationID uint) error {
	return s.db.WithContext(ctx).
		Where("allocation_id = ?", allocationID).
		Delete(&model.ShopPackageAllocation{}).Error
}
