package packagepkg

import (
	"context"
	"fmt"
	"time"

	"gorm.io/gorm"

	"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"
	"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"
)

type Service struct {
	packageStore           *postgres.PackageStore
	packageSeriesStore     *postgres.PackageSeriesStore
	packageAllocationStore *postgres.ShopPackageAllocationStore
	seriesAllocationStore  *postgres.ShopSeriesAllocationStore
}

func New(
	packageStore *postgres.PackageStore,
	packageSeriesStore *postgres.PackageSeriesStore,
	packageAllocationStore *postgres.ShopPackageAllocationStore,
	seriesAllocationStore *postgres.ShopSeriesAllocationStore,
) *Service {
	return &Service{
		packageStore:           packageStore,
		packageSeriesStore:     packageSeriesStore,
		packageAllocationStore: packageAllocationStore,
		seriesAllocationStore:  seriesAllocationStore,
	}
}

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

	existing, _ := s.packageStore.GetByCode(ctx, req.PackageCode)
	if existing != nil {
		return nil, errors.New(errors.CodeConflict, "套餐编码已存在")
	}

	var seriesName *string
	if req.SeriesID != nil && *req.SeriesID > 0 {
		series, err := s.packageSeriesStore.GetByID(ctx, *req.SeriesID)
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				return nil, errors.New(errors.CodeNotFound, "套餐系列不存在")
			}
			return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐系列失败")
		}
		seriesName = &series.SeriesName
	}

	pkg := &model.Package{
		PackageCode:    req.PackageCode,
		PackageName:    req.PackageName,
		PackageType:    req.PackageType,
		DurationMonths: req.DurationMonths,
		Price:          req.Price,
		Status:         constants.StatusEnabled,
		ShelfStatus:    2,
	}
	if req.SeriesID != nil {
		pkg.SeriesID = *req.SeriesID
	}
	if req.DataType != nil {
		pkg.DataType = *req.DataType
	}
	if req.RealDataMB != nil {
		pkg.RealDataMB = *req.RealDataMB
	}
	if req.VirtualDataMB != nil {
		pkg.VirtualDataMB = *req.VirtualDataMB
	}
	if req.DataAmountMB != nil {
		pkg.DataAmountMB = *req.DataAmountMB
	}
	if req.SuggestedCostPrice != nil {
		pkg.SuggestedCostPrice = *req.SuggestedCostPrice
	}
	if req.SuggestedRetailPrice != nil {
		pkg.SuggestedRetailPrice = *req.SuggestedRetailPrice
	}
	pkg.Creator = currentUserID

	if err := s.packageStore.Create(ctx, pkg); err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "创建套餐失败")
	}

	resp := s.toResponse(ctx, pkg)
	resp.SeriesName = seriesName
	return resp, nil
}

func (s *Service) Get(ctx context.Context, id uint) (*dto.PackageResponse, error) {
	pkg, err := s.packageStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "套餐不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
	}

	resp := s.toResponse(ctx, pkg)
	// 查询系列名称
	if pkg.SeriesID > 0 {
		series, err := s.packageSeriesStore.GetByID(ctx, pkg.SeriesID)
		if err == nil {
			resp.SeriesName = &series.SeriesName
		}
	}
	return resp, nil
}

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

	pkg, err := s.packageStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "套餐不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
	}

	var seriesName *string
	if req.SeriesID != nil && *req.SeriesID > 0 {
		series, err := s.packageSeriesStore.GetByID(ctx, *req.SeriesID)
		if err != nil {
			if err == gorm.ErrRecordNotFound {
				return nil, errors.New(errors.CodeNotFound, "套餐系列不存在")
			}
			return nil, errors.Wrap(errors.CodeInternalError, err, "获取套餐系列失败")
		}
		pkg.SeriesID = *req.SeriesID
		seriesName = &series.SeriesName
	} else if pkg.SeriesID > 0 {
		// 如果没有更新 SeriesID，但现有套餐有 SeriesID，则查询当前的系列名称
		series, err := s.packageSeriesStore.GetByID(ctx, pkg.SeriesID)
		if err == nil {
			seriesName = &series.SeriesName
		}
	}

	if req.PackageName != nil {
		pkg.PackageName = *req.PackageName
	}
	if req.PackageType != nil {
		pkg.PackageType = *req.PackageType
	}
	if req.DurationMonths != nil {
		pkg.DurationMonths = *req.DurationMonths
	}
	if req.DataType != nil {
		pkg.DataType = *req.DataType
	}
	if req.RealDataMB != nil {
		pkg.RealDataMB = *req.RealDataMB
	}
	if req.VirtualDataMB != nil {
		pkg.VirtualDataMB = *req.VirtualDataMB
	}
	if req.DataAmountMB != nil {
		pkg.DataAmountMB = *req.DataAmountMB
	}
	if req.Price != nil {
		pkg.Price = *req.Price
	}
	if req.SuggestedCostPrice != nil {
		pkg.SuggestedCostPrice = *req.SuggestedCostPrice
	}
	if req.SuggestedRetailPrice != nil {
		pkg.SuggestedRetailPrice = *req.SuggestedRetailPrice
	}
	pkg.Updater = currentUserID

	if err := s.packageStore.Update(ctx, pkg); err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "更新套餐失败")
	}

	resp := s.toResponse(ctx, pkg)
	resp.SeriesName = seriesName
	return resp, nil
}

func (s *Service) Delete(ctx context.Context, id uint) error {
	_, err := s.packageStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeNotFound, "套餐不存在")
		}
		return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
	}

	if err := s.packageStore.Delete(ctx, id); err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "删除套餐失败")
	}

	return nil
}

func (s *Service) List(ctx context.Context, req *dto.PackageListRequest) ([]*dto.PackageResponse, int64, error) {
	opts := &store.QueryOptions{
		Page:     req.Page,
		PageSize: req.PageSize,
		OrderBy:  "id DESC",
	}
	if opts.Page == 0 {
		opts.Page = 1
	}
	if opts.PageSize == 0 {
		opts.PageSize = constants.DefaultPageSize
	}

	filters := make(map[string]interface{})
	if req.PackageName != nil {
		filters["package_name"] = *req.PackageName
	}
	if req.SeriesID != nil {
		filters["series_id"] = *req.SeriesID
	}
	if req.Status != nil {
		filters["status"] = *req.Status
	}
	if req.ShelfStatus != nil {
		filters["shelf_status"] = *req.ShelfStatus
	}
	if req.PackageType != nil {
		filters["package_type"] = *req.PackageType
	}

	packages, total, err := s.packageStore.List(ctx, opts, filters)
	if err != nil {
		return nil, 0, errors.Wrap(errors.CodeInternalError, err, "查询套餐列表失败")
	}

	// 收集所有唯一的 series_id
	seriesIDMap := make(map[uint]bool)
	for _, pkg := range packages {
		if pkg.SeriesID > 0 {
			seriesIDMap[pkg.SeriesID] = true
		}
	}

	// 批量查询套餐系列
	seriesMap := make(map[uint]string)
	if len(seriesIDMap) > 0 {
		seriesIDs := make([]uint, 0, len(seriesIDMap))
		for id := range seriesIDMap {
			seriesIDs = append(seriesIDs, id)
		}
		seriesList, err := s.packageSeriesStore.GetByIDs(ctx, seriesIDs)
		if err != nil {
			return nil, 0, errors.Wrap(errors.CodeInternalError, err, "批量查询套餐系列失败")
		}
		for _, series := range seriesList {
			seriesMap[series.ID] = series.SeriesName
		}
	}

	// 构建响应，填充系列名称
	responses := make([]*dto.PackageResponse, len(packages))
	for i, pkg := range packages {
		resp := s.toResponse(ctx, pkg)
		if pkg.SeriesID > 0 {
			if seriesName, ok := seriesMap[pkg.SeriesID]; ok {
				resp.SeriesName = &seriesName
			}
		}
		responses[i] = resp
	}

	return responses, total, nil
}

func (s *Service) UpdateStatus(ctx context.Context, id uint, status int) error {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	pkg, err := s.packageStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeNotFound, "套餐不存在")
		}
		return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
	}

	pkg.Status = status
	pkg.Updater = currentUserID

	if status == constants.StatusDisabled {
		pkg.ShelfStatus = 2
	}

	if err := s.packageStore.Update(ctx, pkg); err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "更新套餐状态失败")
	}

	return nil
}

func (s *Service) UpdateShelfStatus(ctx context.Context, id uint, shelfStatus int) error {
	currentUserID := middleware.GetUserIDFromContext(ctx)
	if currentUserID == 0 {
		return errors.New(errors.CodeUnauthorized, "未授权访问")
	}

	pkg, err := s.packageStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeNotFound, "套餐不存在")
		}
		return errors.Wrap(errors.CodeInternalError, err, "获取套餐失败")
	}

	if shelfStatus == 1 && pkg.Status == constants.StatusDisabled {
		return errors.New(errors.CodeInvalidStatus, "禁用的套餐不能上架，请先启用")
	}

	pkg.ShelfStatus = shelfStatus
	pkg.Updater = currentUserID

	if err := s.packageStore.Update(ctx, pkg); err != nil {
		return errors.Wrap(errors.CodeInternalError, err, "更新套餐上架状态失败")
	}

	return nil
}

func (s *Service) toResponse(ctx context.Context, pkg *model.Package) *dto.PackageResponse {
	var seriesID *uint
	if pkg.SeriesID > 0 {
		seriesID = &pkg.SeriesID
	}

	resp := &dto.PackageResponse{
		ID:                   pkg.ID,
		PackageCode:          pkg.PackageCode,
		PackageName:          pkg.PackageName,
		SeriesID:             seriesID,
		PackageType:          pkg.PackageType,
		DurationMonths:       pkg.DurationMonths,
		DataType:             pkg.DataType,
		RealDataMB:           pkg.RealDataMB,
		VirtualDataMB:        pkg.VirtualDataMB,
		DataAmountMB:         pkg.DataAmountMB,
		Price:                pkg.Price,
		SuggestedCostPrice:   pkg.SuggestedCostPrice,
		SuggestedRetailPrice: pkg.SuggestedRetailPrice,
		Status:               pkg.Status,
		ShelfStatus:          pkg.ShelfStatus,
		CreatedAt:            pkg.CreatedAt.Format(time.RFC3339),
		UpdatedAt:            pkg.UpdatedAt.Format(time.RFC3339),
	}

	userType := middleware.GetUserTypeFromContext(ctx)
	shopID := middleware.GetShopIDFromContext(ctx)
	if userType == constants.UserTypeAgent && shopID > 0 {
		allocation, err := s.packageAllocationStore.GetByShopAndPackage(ctx, shopID, pkg.ID)
		if err == nil && allocation != nil {
			resp.CostPrice = &allocation.CostPrice
			profitMargin := pkg.SuggestedRetailPrice - allocation.CostPrice
			resp.ProfitMargin = &profitMargin

			commissionInfo := s.getCommissionInfo(ctx, allocation.AllocationID)
			if commissionInfo != nil {
				resp.CurrentCommissionRate = commissionInfo.CurrentRate
				resp.TierInfo = commissionInfo
			}
		}
	}

	return resp
}

func (s *Service) getCommissionInfo(ctx context.Context, allocationID uint) *dto.CommissionTierInfo {
	seriesAllocation, err := s.seriesAllocationStore.GetByID(ctx, allocationID)
	if err != nil {
		return nil
	}

	info := &dto.CommissionTierInfo{}

	if seriesAllocation.BaseCommissionMode == constants.CommissionModeFixed {
		info.CurrentRate = fmt.Sprintf("%.2f元/单", float64(seriesAllocation.BaseCommissionValue)/100)
	} else {
		info.CurrentRate = fmt.Sprintf("%.1f%%", float64(seriesAllocation.BaseCommissionValue)/10)
	}

	return info
}
