package central

import (
	"context"
	"encoding/json"
	"strconv"
	"time"

	"message-service/commons/chatgpttemplate"
	"message-service/commons/utils"
	"message-service/internal/bean/dto"
	"message-service/internal/bean/entity"
	"message-service/internal/dao"

	"github.com/google/uuid"
	"github.com/tidbcloud/tiinf/errs"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

func CheckInteractReqeustValid(req *dto.InteractRequest) error {
	if req.Question == "" {
		return errs.NewBadRequest("question is empty", nil)
	}
	/*
		if req.BotType == "" {
			return errs.NewBadRequest("BotType is empty", nil)
		}
	*/
	if req.Question == "" {
		return errs.NewBadRequest("Question is empty", nil)
	}
	return nil
}

func InteractBot(ctx context.Context, req *dto.InteractRequest, createdBy string) (*dto.InteractResponse, error) {
	startTime := time.Now()
	tilog.Info(ctx, "service interact bot: start", zap.Any("req", req), zap.Any("createdBy", createdBy))
	if req.SessionID != "" {
		recs, err := dao.GetBotInteractRecordBySessionIDCreatedBy(req.SessionID, createdBy)
		if err != nil {
			tilog.Error(ctx, "service interact bot: get interact record by session_id created_by error", zap.Any("err", err))
			return nil, err
		}
		if len(recs) == 0 {
			tilog.Warn(ctx, "service interact bot: session_id created_by relate record not found in db", zap.Any("session_id", req.SessionID), zap.Any("created_by", createdBy))
			return nil, errs.NewBadRequest("session_id invalid", nil)
		}
	}
	if req.SessionID == "" {
		req.SessionID = uuid.New().String()
		tilog.Info(ctx, "service interact bot: open a new session", zap.Any("sessionID", req.SessionID))
	}

	//oneHourBefore := utils.JsonTime{Time: time.Now().Add(-1 * time.Hour)}
	//recs, err := dao.GetBotInteractRecordByCreatedByQuestionGECreatedAt(createdBy, req.Question, oneHourBefore)
	//if err == nil && len(recs) > 0 {
	//	rec := recs[0]
	//	tilog.Info(ctx, "interact bot: find last one hour valid interact record", zap.Any("record", rec))
	//	completion, code := GetRespByCompletion(req.BotType, rec.Response)
	//	resp := &dto.InteractResponse{
	//		SessionID: req.SessionID,
	//		Question:  req.Question,
	//		Prompt:    rec.Prompt,
	//		Response:  completion,
	//		Code:      code,
	//	}
	//	return resp, nil
	//}

	prompt, completion, result, err := CreateCompletionWithReq(ctx, req)
	tilog.Info(ctx, "service interact bot: create completion result", zap.Any("prompt", prompt), zap.String("completion", completion), zap.Any("err", err))
	if err != nil {
		tilog.Info(ctx, "service interact bot: create completion error", zap.String("prompt", req.Question), zap.Any("err", err))
		resp := &dto.InteractResponse{
			SessionID:     req.SessionID,
			Question:      req.Question,
			Prompt:        prompt.Content,
			PromptVersion: prompt.Version,
			Response:      defaultUnknownAIErrorMsg,
			Code:          COMPLETION_CODE_UNKNOWN_FAILED,
		}
		return resp, nil
	}

	record := createRecord(req, prompt, completion, createdBy)
	tilog.Info(ctx, "service interact bot: create interact record", zap.Any("rec", record))
	_, err = dao.CreateBotInteractRecord(record)
	if err != nil {
		tilog.Error(ctx, "service interact bot: db create interact record error", zap.Any("err", err))
		return nil, err
	}
	completion, code := GetRespByCompletion(req.BotType, completion)
	endTime := time.Now()
	executeTime := endTime.Sub(startTime).Milliseconds()

	var tokenUsed int
	if result != nil {
		tokenUsed = result.Usage.TotalTokens
	}
	resp := &dto.InteractResponse{
		SessionID:     req.SessionID,
		Question:      req.Question,
		Prompt:        prompt.Content,
		PromptVersion: prompt.Version,
		Response:      completion,
		Code:          code,
		StartTime:     startTime.Format("2006-01-02 15:04:05"),
		EndTime:       endTime.Format("2006-01-02 15:04:05"),
		StartTimeMS:   startTime.UnixMilli(),
		EndTimeMS:     endTime.UnixMilli(),
		ExecuteTime:   strconv.FormatInt(executeTime, 10),
		TokenUsed:     tokenUsed,
	}

	tilog.Info(ctx, "service interact bot: gen rsp", zap.Any("rsp", resp))

	return resp, nil
}

func createRecord(question *dto.InteractRequest, prompt chatgpttemplate.Prompt, completion, createdBy string) *entity.BotInteractRecord {
	marshal, _ := json.Marshal(question)

	now := utils.JsonTime{Time: time.Now()}

	record := entity.BotInteractRecord{
		SessionID:     question.SessionID,
		Question:      question.Question,
		QuestionCtx:   string(marshal),
		Prompt:        prompt.Content,
		PromptVersion: prompt.Version,
		Response:      completion,
		CreatedBy:     createdBy,
		CreatedAt:     now,
		UpdatedAt:     now,
	}
	return &record
}

func ListInteractBotRecord(_ context.Context, param *dto.ListInteractRecParam) (*dto.ListInteractRecResult, error) {
	return dao.ListBotInteractRecord(param)
}
