package post_fields_worker

import (
	"amocrm/internal/models"
	"amocrm/internal/repository"
	"amocrm/pkg/amoClient"
	"context"
	"fmt"
	"go.uber.org/zap"
	"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal"
	"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/repository/amo"
	"time"
)

type Deps struct {
	AmoRepo   *dal.AmoDal
	AmoClient *amoClient.Amo
	RedisRepo *repository.Repository
	Logger    *zap.Logger
}

type PostFields struct {
	amoRepo   *dal.AmoDal
	amoClient *amoClient.Amo
	redisRepo *repository.Repository
	logger    *zap.Logger
}

func NewPostFieldsWC(deps Deps) *PostFields {
	return &PostFields{
		amoRepo:   deps.AmoRepo,
		amoClient: deps.AmoClient,
		redisRepo: deps.RedisRepo,
		logger:    deps.Logger,
	}
}

func (wc *PostFields) Start(ctx context.Context) {
	ticker := time.NewTicker(10 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			wc.processTask(ctx)

		case <-ctx.Done():
			return
		}
	}
}

func (wc *PostFields) processTask(ctx context.Context) {
	dealsDataForUpdate, forRestoringMap, err := wc.redisRepo.FetchingDeals(ctx)
	if err != nil {
		wc.logger.Error("error fetching deals for update in redis", zap.Error(err))
		return
	}
	for token, dealsData := range dealsDataForUpdate {
		errorCheckerMap, err := wc.sendForUpdate(ctx, token, dealsData)
		if err != nil {
			wc.logger.Error("error updating deals fields in db", zap.Error(err))
		}

		for dealID, _ := range errorCheckerMap {
			restoringData := forRestoringMap[dealID]
			err = wc.redisRepo.CachingDealToRedis(ctx, restoringData.SaveDeal)
			if err != nil {
				wc.logger.Error("error restoring deal in redis", zap.Error(err))
				return
			}

			err = wc.redisRepo.CachingLeadFieldsToRedis(ctx, restoringData.SaveDeal.AnswerID, restoringData.LeadFields)
			if err != nil {
				wc.logger.Error("error restoring deal fields in redis", zap.Error(err))
				return
			}
		}
	}
}

func (wc *PostFields) sendForUpdate(ctx context.Context, token string, dealsData []models.MappingDealsData) (map[int32]struct{}, error) {
	errorCheckerMap := make(map[int32]struct{})
	var subDomain string
	var reqToUpdate []models.UpdateDealReq
	for _, data := range dealsData {
		subDomain = data.SubDomain
		req := models.UpdateDealReq{
			DealID:             data.DealID,
			CustomFieldsValues: data.LeadFields,
		}
		fmt.Println("AAAA", data.LeadFields)
		reqToUpdate = append(reqToUpdate, req)
	}

	resp, errResp := wc.amoClient.UpdatingDeal(reqToUpdate, token, subDomain)
	if errResp != nil {
		// todo также логирование ошибки в тг
		wc.logger.Error("error sendig request for update deal fields", zap.Error(errResp))
		for _, data := range reqToUpdate {
			errorCheckerMap[data.DealID] = struct{}{}
		}
		return errorCheckerMap, errResp
	}

	err := wc.updateDealStatus(ctx, DealStatus{
		Resp:        resp,
		AccessToken: token,
	})

	if err != nil {
		wc.logger.Error("error update deal Status after updating fields", zap.Error(err))
		return errorCheckerMap, err
	}

	return errorCheckerMap, nil
}

type DealStatus struct {
	Resp        *models.UpdateDealResp
	AccessToken string
}

func (wc *PostFields) updateDealStatus(ctx context.Context, deps DealStatus) error {
	status := "success"
	for _, lead := range deps.Resp.Embedded.Leads {
		dealID := lead.ID
		err := wc.amoRepo.AmoRepo.UpdatingDealAmoStatus(ctx, amo.SaveDealAmoDeps{DealID: dealID, AccessToken: deps.AccessToken, Status: status})
		if err != nil {
			wc.logger.Error("error saving deal status update to database", zap.Error(err))
			return err
		}
	}

	return nil
}

func (wc *PostFields) Stop(_ context.Context) error {
	return nil
}
