package selection_service

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"reflect"
	"time"
	"youngee_b_api/db"
	"youngee_b_api/model/common_model"
	"youngee_b_api/model/gorm_model"
	"youngee_b_api/model/http_model"
	"youngee_b_api/pack"
	"youngee_b_api/util"

	"github.com/caixw/lib.go/conv"
)

var Selection *selection

type selection struct {
}

func (*selection) Create(ctx context.Context, request http_model.CreateSelectionRequest, enterpriseId string) (*http_model.CreateSelectionData, error) {
	// 1. 检查该企业id和商品id有无选品
	//selectionInfo, err := db.GetSelectionByEnterpiseIdAndProductId(ctx, enterpriseId, conv.MustInt(request.ProductId, 0))
	//if err != nil {
	//	return nil, err
	//}
	//if selectionInfo != nil {
	//	return nil, errors.New("该商品下选品已存在")
	//}

	// 2. 数据准备
	// a) 生成选品id
	selectionId := util.GetSelectionID()
	// b) 查找关联商品信息
	product, err := db.GetProductByID(ctx, conv.MustInt64(request.ProductId, 0))
	if err != nil {
		return nil, err
	}
	productPhotos, err := db.GetProductPhotoByProductID(ctx, conv.MustInt64(request.ProductId, 0))
	productInfoToJson, _ := json.Marshal(product)
	productPhotosToJson, _ := json.Marshal(productPhotos)
	// c) 选品名称
	selectionName := product.BrandName + "-" + product.ProductName

	// 3. 创建选品
	taskDdl := time.Time{} //赋零值
	taskDdl, _ = time.ParseInLocation("2006-01-02 15:04:05", "2026-01-01 08:00:00", time.Local)
	newSelection := gorm_model.YounggeeSelectionInfo{
		SelectionID:      selectionId,
		SelectionName:    selectionName,
		SelectionStatus:  1,
		ProductID:        conv.MustInt(request.ProductId, 0),
		EnterpriseID:     enterpriseId,
		Platform:         conv.MustInt(request.Platform, 0),
		ProductSnap:      string(productInfoToJson),
		ProductPhotoSnap: string(productPhotosToJson),
		CreatedAt:        time.Now(),
		SubmitAt:         time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
		PassAt:           time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
		PayAt:            time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
		FinishAt:         time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC),
		TaskDdl:          taskDdl,
		EstimatedCost:    "0",
		TaskReward:       "0",
		SettlementAmount: "0",
	}
	//Selection := gorm_model.YounggeeSelectionInfo{}
	err = db.CreateSelection(ctx, newSelection)
	if err != nil {
		return nil, err
	}

	res := &http_model.CreateSelectionData{
		SelectionId: selectionId,
	}
	return res, nil
}

func (*selection) Update(ctx context.Context, request http_model.UpdateSelectionRequest, enterpriseId string) (*http_model.UpdateSelectionData, error) {
	// 1. 检查该选品是否存在
	selectionInfo, err := db.GetSelectionById(ctx, request.SelectionID)
	if err != nil {
		return nil, err
	}
	if selectionInfo == nil {
		return nil, errors.New("选品不存在")
	}

	// 2. 数据准备
	// a) 查找关联商品信息
	product, err := db.GetProductByID(ctx, conv.MustInt64(request.ProductId, 0))
	if err != nil {
		return nil, err
	}
	productPhotos, err := db.GetProductPhotoByProductID(ctx, conv.MustInt64(request.ProductId, 0))
	productInfoToJson, _ := json.Marshal(product)
	productPhotosToJson, _ := json.Marshal(productPhotos)
	// b) 选品名称
	selectionName := product.BrandName + "-" + product.ProductName
	// c) 计算预估成本（如果有）
	var estimatedCost float64
	if conv.MustInt(request.TaskMode, 0) == 1 {
		estimatedCost = conv.MustFloat64(request.TaskReward, 0) * conv.MustFloat64(request.SampleNum, 0)
	}
	estimatedCostToString, _ := conv.String(estimatedCost)
	// d) 任务截止时间
	taskDdl := time.Time{} //赋零值
	taskDdl, _ = time.ParseInLocation("2006-01-02 15:04:05", request.TaskDdl, time.Local)
	// f) 更新选品状态
	if request.SelectionStatus != 2 {
		request.SelectionStatus = 1
	}

	updateSelection := gorm_model.YounggeeSelectionInfo{
		SelectionID:      request.SelectionID,
		SelectionStatus:  request.SelectionStatus,
		SelectionName:    selectionName,
		EnterpriseID:     enterpriseId,
		ProductID:        conv.MustInt(request.ProductId, 0),
		ContentType:      conv.MustInt(request.ContentType, 0),
		TaskMode:         conv.MustInt(request.TaskMode, 0),
		Platform:         conv.MustInt(request.Platform, 0),
		SampleMode:       conv.MustInt(request.SampleMode, 0),
		ProductUrl:       request.ProductUrl,
		SampleNum:        conv.MustInt(request.SampleNum, 0),
		RemainNum:        conv.MustInt(request.SampleNum, 0),
		CommissionRate:   conv.MustFloat64(request.CommissionRate, 0),
		TaskReward:       conv.MustString(request.TaskReward, ""),
		SettlementAmount: conv.MustString(request.SettlementAmount, ""),
		EstimatedCost:    estimatedCostToString,
		SampleCondition:  request.SampleCondition,
		RewardCondition:  request.RewardCondition,
		TaskDdl:          taskDdl,
		Detail:           request.Detail,
		ProductSnap:      string(productInfoToJson),
		ProductPhotoSnap: string(productPhotosToJson),
		CreatedAt:        selectionInfo.CreatedAt,
		UpdatedAt:        time.Now(),
		SubmitAt:         time.Now(),
	}
	// 合并传入参数和数据表中原记录，若传入参数字段值为空，则将字段赋值为原记录中值
	//fmt.Printf("MergeTest %+v %+v", updateSelection, selectionInfo)
	result := util.MergeStructValue(&updateSelection, selectionInfo)
	// 利用反射机制将interface类型转换为结构体类型
	v := reflect.ValueOf(&result).Elem()
	if v.Kind() == reflect.Struct {
		updateSelection = v.Interface().(gorm_model.YounggeeSelectionInfo)
		//fmt.Println(p)
	}

	// 3. 更新选品
	err = db.UpdateSelection(ctx, updateSelection)
	if err != nil {
		return nil, err
	}

	// 4. 更新选品brief和示例
	if request.SecBrief != nil {
		// 删除已有brief
		err = db.DeleteSecBriefBySelectionId(ctx, selectionInfo.SelectionID)
		if err != nil {
			return nil, err
		}
		// 插入新的biref
		for _, v := range request.SecBrief {
			brief := gorm_model.YounggeeSecBrief{
				SelectionID: selectionInfo.SelectionID,
				FileUid:     conv.MustString(v.FileUid, ""),
				FileName:    v.Name,
				FileUrl:     v.FileUrl,
				CreatedAt:   time.Now(),
			}
			err = db.CreateSecBrief(ctx, brief)
			if err != nil {
				return nil, err
			}
		}
	}

	if request.SecExample != nil {
		// 删除已有示例
		err = db.DeleteSecExampleBySelectionId(ctx, selectionInfo.SelectionID)
		if err != nil {
			return nil, err
		}
		// 插入新的示例
		for _, v := range request.SecExample {
			Example := gorm_model.YounggeeSecExample{
				SelectionID: selectionInfo.SelectionID,
				FileUid:     conv.MustString(v.FileUrl, ""),
				FileName:    v.Name,
				FileUrl:     v.FileUrl,
				CreatedAt:   time.Now(),
			}
			err = db.CreateSecExample(ctx, Example)
			if err != nil {
				return nil, err
			}
		}
	}

	res := &http_model.UpdateSelectionData{
		SelectionId: updateSelection.SelectionID,
	}
	return res, nil
}

func (*selection) Pay(ctx context.Context, request http_model.PaySelectionRequest, enterpriseId string) (*http_model.PaySelectionData, error) {
	// 校验
	// 1. 账户余额是否足够
	enterprise, err := db.GetEnterpriseByEnterpriseID(ctx, enterpriseId)
	if err != nil {
		return nil, err
	}
	if enterprise.AvailableBalance < request.PayMoney {
		return nil, errors.New("账户余额不足")
	}
	// 2. 选品项目状态是否正确
	selectionInfo, err := db.GetSelectionById(ctx, request.SelectionId)
	fmt.Printf("校验selection %+v %+v", selectionInfo.SelectionStatus, selectionInfo)
	if err != nil {
		return nil, err
	}
	if selectionInfo == nil {
		return nil, errors.New("选品不存在")
	}
	if selectionInfo.SelectionStatus != 4 {
		return nil, errors.New("选品状态有误")
	}

	// 支付
	err = db.PaySelection(ctx, enterpriseId, request.PayMoney, request.SelectionId)
	if err != nil {
		return nil, err
	}

	res := &http_model.PaySelectionData{
		SelectionId: request.SelectionId,
	}
	return res, nil
}

func (s *selection) GetAllSelection(ctx context.Context, enterpriseID string, pageSize, pageNum int64, conditions *common_model.SelectionConditions) (*http_model.SelectionData, error) {
	SelectionList, total, err := db.GetSelectionList(ctx, enterpriseID, pageSize, pageNum, conditions)
	if err != nil {
		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetAllSelection error,err:%+v", err)
		return nil, err
	}
	SelectionListData := new(http_model.SelectionData)
	SelectionListData.SelectionInfo = pack.MGormSelectionToHttpSelectionPreview(SelectionList)
	SelectionListData.Total = conv.MustString(total, "")
	return SelectionListData, nil
}

func (s *selection) GetSelectionDetail(ctx *gin.Context, selectionId, enterpriseID string) (*http_model.SelectionDetail, error) {
	selectionDetail := http_model.SelectionDetail{}
	selectionInfo, err := db.GetSelectionById(ctx, selectionId)

	if err != nil {
		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetSelectionInfo error,err:%+v", err)
		return nil, err
	}
	selectionBriefInfo, err := db.GetSelectionBriefInfo(ctx, selectionId)
	if err != nil {
		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetSelectionBriefInfo error,err:%+v", err)
		return nil, err
	}
	selectionExampleInfo, err := db.GetSelectionExampleInfo(ctx, selectionId)
	if err != nil {
		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetSelectionExampleInfo error,err:%+v", err)
		return nil, err
	}
	productInfo, err := db.GetProductInfoBySelectionId(ctx, selectionId)
	if err != nil {
		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetProductInfo error,err:%+v", err)
		return nil, err
	}
	productPhotoInfo, err := db.GetProductPhotoInfoBySelectionId(ctx, selectionId)
	if err != nil {
		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetProductPhotoInfo error,err:%+v", err)
		return nil, err
	}
	selectionDetail.SelectionBrief = selectionBriefInfo
	selectionDetail.SelectionInfo = selectionInfo
	selectionDetail.SelectionExample = selectionExampleInfo
	selectionDetail.ProductInfo = productInfo
	selectionDetail.ProductPhotoInfo = productPhotoInfo
	return &selectionDetail, nil
}

func (s *selection) SelectionSquare(ctx context.Context, req http_model.GetAllSelectionRequest, condition http_model.SelectionSquareCondition) (*http_model.SelectionBriefInfoPreview, error) {
	SelectionList, total, err := db.GetSelectionInfoList(ctx, req.PageNum, req.PageSize, condition)
	if err != nil {
		logrus.WithContext(ctx).Errorf("[selectionDB service] call GetAllSelection error,err:%+v", err)
		return nil, err
	}
	SelectionListData := new(http_model.SelectionBriefInfoPreview)
	SelectionListData.SelectionBriefInfo = SelectionList
	SelectionListData.Total = conv.MustString(total, "")
	fmt.Printf("SelectionInfo %+v", SelectionListData)
	return SelectionListData, nil
}
