package postgres

import (
	"context"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/store"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"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
	query := s.db.WithContext(ctx).Where("id = ?", id)
	// 应用数据权限过滤：代理只能访问自己分配出去的记录
	query = middleware.ApplyAllocatorShopFilter(ctx, query)
	if err := query.First(&allocation).Error; err != nil {
		return nil, err
	}
	return &allocation, nil
}

// GetByIDForSystem 根据ID获取分配记录（不应用数据权限过滤）
// 用于 Service 层需要先查到记录再做业务权限校验的场景
func (s *ShopPackageAllocationStore) GetByIDForSystem(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
	query := s.db.WithContext(ctx).Where("shop_id = ? AND package_id = ?", shopID, packageID)
	// 应用数据权限过滤
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.First(&allocation).Error; err != nil {
		return nil, err
	}
	return &allocation, nil
}

// GetByShopAndPackageForSystem 根据店铺和套餐查询分配记录（不应用数据权限过滤）
// 用于系统内部查询场景（如购买校验），避免因 ctx 权限限制导致无法查到目标记录
func (s *ShopPackageAllocationStore) GetByShopAndPackageForSystem(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{})
	// 应用数据权限过滤：代理只能看到自己分配出去的记录
	query = middleware.ApplyAllocatorShopFilter(ctx, query)

	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 seriesAllocationID, ok := filters["series_allocation_id"].(uint); ok && seriesAllocationID > 0 {
		query = query.Where("series_allocation_id = ?", seriesAllocationID)
	}
	if allocatorShopID, ok := filters["allocator_shop_id"].(uint); ok {
		query = query.Where("allocator_shop_id = ?", allocatorShopID)
	}
	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
}

// UpdateShelfStatus 更新分配记录的上下架状态
func (s *ShopPackageAllocationStore) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus int, updater uint) error {
	return s.db.WithContext(ctx).
		Model(&model.ShopPackageAllocation{}).
		Where("id = ?", id).
		Updates(map[string]interface{}{
			"shelf_status": shelfStatus,
			"updater":      updater,
		}).Error
}

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

func (s *ShopPackageAllocationStore) GetByShopID(ctx context.Context, shopID uint) ([]*model.ShopPackageAllocation, error) {
	var allocations []*model.ShopPackageAllocation
	query := s.db.WithContext(ctx).Where("shop_id = ? AND status = 1", shopID)
	// 应用数据权限过滤
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.Find(&allocations).Error; err != nil {
		return nil, err
	}
	return allocations, nil
}

func (s *ShopPackageAllocationStore) GetByShopAndPackages(ctx context.Context, shopID uint, packageIDs []uint) ([]*model.ShopPackageAllocation, error) {
	var allocations []*model.ShopPackageAllocation
	query := s.db.WithContext(ctx).
		Where("shop_id = ? AND package_id IN ? AND status = 1", shopID, packageIDs)
	// 应用数据权限过滤
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.Find(&allocations).Error; err != nil {
		return nil, err
	}
	return allocations, nil
}

func (s *ShopPackageAllocationStore) GetBySeriesAllocationID(ctx context.Context, seriesAllocationID uint) ([]*model.ShopPackageAllocation, error) {
	var allocations []*model.ShopPackageAllocation
	query := s.db.WithContext(ctx).
		Where("series_allocation_id = ? AND status = 1", seriesAllocationID)
	// 应用数据权限过滤
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.Find(&allocations).Error; err != nil {
		return nil, err
	}
	return allocations, nil
}

func (s *ShopPackageAllocationStore) CountBySeriesAllocationID(ctx context.Context, seriesAllocationID uint) (int64, error) {
	var count int64
	if err := s.db.WithContext(ctx).
		Model(&model.ShopPackageAllocation{}).
		Where("series_allocation_id = ?", seriesAllocationID).
		Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}
