package biz

import (
	"ai_scheduler/internal/data/impl"
	"ai_scheduler/internal/data/model"
	"ai_scheduler/internal/data/mongo_model"
	"ai_scheduler/internal/entitys"
	"ai_scheduler/internal/pkg"
	"fmt"
	"time"

	"context"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"xorm.io/builder"
)

type AdviceProjectBiz struct {
	AdvicerProjectMongo  *mongo_model.AdvicerProjectMongo
	adviceProjectImpl    *impl.AdviceProjectImpl
	aiAdviceModelSupImpl *impl.AiAdviceModelSupImpl
	mongo                *pkg.Mongo
}

func NewAdviceProjectBiz(
	advicerProjectMongo *mongo_model.AdvicerProjectMongo,
	adviceProjectImpl *impl.AdviceProjectImpl,
	aiAdviceModelSupImpl *impl.AiAdviceModelSupImpl,
	mongo *pkg.Mongo,
) *AdviceProjectBiz {
	return &AdviceProjectBiz{
		AdvicerProjectMongo:  advicerProjectMongo,
		mongo:                mongo,
		adviceProjectImpl:    adviceProjectImpl,
		aiAdviceModelSupImpl: aiAdviceModelSupImpl,
	}
}

func (a *AdviceProjectBiz) BaseAdd(ctx context.Context, param *entitys.AdvicerProjectBaseAddReq) (res *entitys.AdvicerProjectBaseAddRes, err error) {
	add := &model.AiAdviceProject{
		Name:       param.Name,
		ModelSupID: param.ModelSupId,
	}
	err = a.adviceProjectImpl.AddWithData(add)
	if err != nil {
		return nil, err
	}
	return &entitys.AdvicerProjectBaseAddRes{
		ProjectId: add.ProjectID,
	}, err
}

func (a *AdviceProjectBiz) BaseUpdate(ctx context.Context, param *entitys.AdvicerProjectBaseUpdateReq) (err error) {
	if param.ProjectId == 0 {
		return
	}
	cond := builder.NewCond()
	cond = cond.And(builder.Eq{"project_id": param.ProjectId})
	err = a.adviceProjectImpl.UpdateByCond(&cond, &model.AiAdviceProject{
		Name:       param.Name,
		ModelSupID: param.ModelSupId,
	})
	return err
}

func (a *AdviceProjectBiz) Add(ctx context.Context, param *entitys.AdvicerProjectAddReq) (id interface{}, err error) {

	res, err := a.mongo.Co(a.AdvicerProjectMongo).InsertOne(ctx, &mongo_model.AdvicerProjectMongo{
		ProjectId:             param.ProjectId,
		ProjectInfo:           param.ProjectInfo,
		RegionValue:           param.RegionValue,
		CompetitionComparison: param.CompetitionComparison,
		CoreSellingPoints:     param.CoreSellingPoints,
		SupportingFacilities:  param.SupportingFacilities,
		DeveloperBacking:      param.DeveloperBacking,
		LastUpdateTime:        time.Now(),
	})

	return res.InsertedID, err
}

func (a *AdviceProjectBiz) Update(ctx context.Context, param *entitys.AdvicerrProjectUpdateReq) (err error) {
	filter := bson.M{}
	if len(param.Id) != 0 {
		objectID, err := primitive.ObjectIDFromHex(param.Id)
		if err != nil {
			return fmt.Errorf("ID转换失败: %w", err)
		}
		filter["_id"] = objectID
	}
	if param.ProjectId != 0 {

		filter["projectId"] = param.ProjectId
	}

	update := bson.M{
		"$set": &mongo_model.AdvicerProjectMongo{
			ProjectId:             param.ProjectId,
			ProjectInfo:           param.ProjectInfo,
			RegionValue:           param.RegionValue,
			CompetitionComparison: param.CompetitionComparison,
			CoreSellingPoints:     param.CoreSellingPoints,
			SupportingFacilities:  param.SupportingFacilities,
			DeveloperBacking:      param.DeveloperBacking,
			LastUpdateTime:        time.Now(),
		},
	}
	res := a.mongo.Co(a.AdvicerProjectMongo).FindOneAndUpdate(ctx, filter, update)
	return res.Err()
}

func (a *AdviceProjectBiz) Info(ctx context.Context, param *entitys.AdvicerProjectInfoReq) (info *entitys.AdvicerProjectInfoRes, err error) {
	configInfo, err := a.ConfigInfo(ctx, param)
	if err != nil {
		return nil, err
	}
	baseInfo, err := a.BaseInfo(configInfo.ProjectId)
	if err != nil {
		return nil, err
	}
	supInfo, err := a.ModelInfo(baseInfo.ModelSupID)
	if err != nil {
		return nil, err
	}
	return &entitys.AdvicerProjectInfoRes{
		ConfigInfo: configInfo,
		Base:       baseInfo,
		ModelInfo:  supInfo,
	}, nil
}

func (a *AdviceProjectBiz) BaseInfo(projectId int32) (baseInfo model.AiAdviceProject, err error) {
	if projectId == 0 {
		return
	}
	cond := builder.NewCond()
	cond = cond.And(builder.Eq{"project_id": projectId})
	err = a.adviceProjectImpl.GetOneBySearchToStrut(&cond, &baseInfo)
	if err != nil {
		return baseInfo, err
	}
	return baseInfo, nil
}

func (a *AdviceProjectBiz) ModelInfo(supId int32) (supInfo model.AiAdviceModelSup, err error) {
	if supId == 0 {
		return
	}
	cond := builder.NewCond()
	cond = cond.And(builder.Eq{"sup_id": supId})
	err = a.aiAdviceModelSupImpl.GetOneBySearchToStrut(&cond, &supInfo)
	if err != nil {
		return supInfo, err
	}
	return supInfo, nil
}

func (a *AdviceProjectBiz) ConfigInfo(ctx context.Context, param *entitys.AdvicerProjectInfoReq) (info mongo_model.AdvicerProjectMongo, err error) {
	filter := bson.M{}

	if param.ProjectId != 0 {
		filter["projectId"] = param.ProjectId
	}

	// 2. _id 条件
	if len(param.Id) != 0 {
		objectID, err := primitive.ObjectIDFromHex(param.Id)
		if err != nil {
			return info, fmt.Errorf("ID转换失败: %w", err)
		}
		filter["_id"] = objectID
	}

	res := a.mongo.Co(a.AdvicerProjectMongo).FindOne(ctx, filter)
	if res.Err() != nil {
		return info, res.Err()
	}
	// 遍历结果

	if err := res.Decode(&info); err != nil {
		return info, err
	}

	return info, nil
}
