package shop_package_batch_pricing

import (
	"context"
	"time"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"gorm.io/gorm"
)

type Service struct {
	db                     *gorm.DB
	packageAllocationStore *postgres.ShopPackageAllocationStore
	priceHistoryStore      *postgres.ShopPackageAllocationPriceHistoryStore
	shopStore              *postgres.ShopStore
}

func New(
	db *gorm.DB,
	packageAllocationStore *postgres.ShopPackageAllocationStore,
	priceHistoryStore *postgres.ShopPackageAllocationPriceHistoryStore,
	shopStore *postgres.ShopStore,
) *Service {
	return &Service{
		db:                     db,
		packageAllocationStore: packageAllocationStore,
		priceHistoryStore:      priceHistoryStore,
		shopStore:              shopStore,
	}
}

func (s *Service) BatchUpdatePricing(ctx context.Context, req *dto.BatchUpdateCostPriceRequest) (*dto.BatchUpdateCostPriceResponse, error) {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return nil, errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	userType := middleware.GetUserTypeFromContext(ctx)
	shopID := middleware.GetShopIDFromContext(ctx)

	if userType == constants.UserTypeAgent && shopID == 0 {
		return nil, errors.New(errors.CodeUnauthorized, "当前用户不属于任何店铺")
	}

	filters := map[string]interface{}{
		"shop_id": req.ShopID,
		"status":  constants.StatusEnabled,
	}

	if req.SeriesID != nil {
		filters["series_id"] = *req.SeriesID
	}

	allocations, _, err := s.packageAllocationStore.List(ctx, nil, filters)
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取分配记录失败")
	}

	if len(allocations) == 0 {
		return nil, errors.New(errors.CodeInvalidParam, "没有找到符合条件的分配记录")
	}

	updatedCount := 0
	now := time.Now()
	affectedIDs := make([]uint, 0)
	skipped := make([]dto.BatchPricingSkipped, 0)

	err = s.db.Transaction(func(tx *gorm.DB) error {
		for _, allocation := range allocations {
			oldPrice := allocation.CostPrice
			newPrice := s.calculateAdjustedPrice(oldPrice, &req.PriceAdjustment)
			if newPrice == oldPrice {
				continue
			}

			// cost_price 锁定检查：存在下级分配记录时跳过
			var subCount int64
			tx.Model(&model.ShopPackageAllocation{}).
				Where("allocator_shop_id = ? AND package_id = ? AND deleted_at IS NULL", allocation.ShopID, allocation.PackageID).
				Count(&subCount)
			if subCount > 0 {
				skipped = append(skipped, dto.BatchPricingSkipped{
					AllocationID: allocation.ID,
					Reason:       "存在下级分配记录，请先回收后再修改成本价",
				})
				continue
			}

			history := &model.ShopPackageAllocationPriceHistory{
				AllocationID:  allocation.ID,
				OldCostPrice:  oldPrice,
				NewCostPrice:  newPrice,
				ChangeReason:  req.ChangeReason,
				ChangedBy:     currentUserID,
				EffectiveFrom: now,
			}
			if err := tx.Create(history).Error; err != nil {
				return errors.Wrap(errors.CodeInternalError, err, "创建价格历史失败")
			}

			allocation.CostPrice = newPrice
			allocation.Updater = currentUserID
			if err := tx.Save(allocation).Error; err != nil {
				return errors.Wrap(errors.CodeInternalError, err, "更新成本价失败")
			}

			affectedIDs = append(affectedIDs, allocation.ID)
			updatedCount++
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	return &dto.BatchUpdateCostPriceResponse{
		UpdatedCount: updatedCount,
		AffectedIDs:  affectedIDs,
		Skipped:      skipped,
	}, nil
}

func (s *Service) calculateAdjustedPrice(basePrice int64, adjustment *dto.PriceAdjustment) int64 {
	if adjustment == nil {
		return basePrice
	}

	if adjustment.Type == "fixed" {
		return basePrice + adjustment.Value
	}

	return basePrice + (basePrice * adjustment.Value / 1000)
}
