package answerwc

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/go-redis/redis/v8"
	"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal"
	"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
	"penahub.gitlab.yandexcloud.net/backend/quiz/worker/senders"
	"penahub.gitlab.yandexcloud.net/backend/quiz/worker/wctools"
	"time"
)

type DepsRespWorker struct {
	Redis      *redis.Client
	Dal        *dal.DAL
	MailClient *senders.MailLeadSender
}

type RespWorker struct {
	deps    DepsRespWorker
	errChan chan<- error
}

func NewRespWorker(deps DepsRespWorker, errChan chan<- error) *RespWorker {
	return &RespWorker{
		deps:    deps,
		errChan: errChan,
	}
}

func (w *RespWorker) Start(ctx context.Context) {
	ticker := time.NewTicker(30 * time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			w.processPendingAnswer(ctx)

		case <-ctx.Done():
			return
		}

	}
}

func (w *RespWorker) processPendingAnswer(ctx context.Context) {
	keys, err := w.deps.Redis.Keys(ctx, "toRespondent:*").Result()
	if err != nil {
		w.reportError(err, "Error retrieving keys from Redis")
		return
	}

	for _, key := range keys {
		func() {
			answerJSON, err := w.deps.Redis.GetDel(ctx, key).Result()
			if err == redis.Nil {
				return
			} else if err != nil {
				w.reportError(err, "Error getting and deleting data from Redis")
				return
			}

			defer func() {
				if r := recover(); r != nil {
					w.reportError(nil, fmt.Sprintf("recovering from panic or error setting redis value %v", r))
					_ = w.deps.Redis.Set(ctx, key, answerJSON, 0).Err()
				}
			}()

			var answer model.Answer
			err = json.Unmarshal([]byte(answerJSON), &answer)
			if err != nil {
				w.reportError(err, "Error unmarshalling answer")
				return
			}

			answerContent, err := wctools.ProcessAnswer(answer.Content)
			if err != nil {
				w.reportError(err, "Error processing answer content")
				return
			}

			quizConfig, accountId, err := w.deps.Dal.QuizRepo.GetQuizConfig(ctx, answer.QuizId)
			if err != nil {
				w.reportError(err, "Error getting quiz config")
				return
			}

			quiz, err := w.deps.Dal.QuizRepo.GetQuizById(ctx, accountId, answer.QuizId)
			if err != nil {
				w.reportError(err, "Error getting quiz")
				return
			}

			quizConfig.Mailing.Reply = quiz.Name

			if quizConfig.Mailing.Theme == "" {
				quizConfig.Mailing.Theme = quiz.Name
			}

			allAnswers, err := w.deps.Dal.WorkerAnsRepo.GetAllAnswersByQuizID(ctx, answer.Session)
			if err != nil {
				w.reportError(err, "Error getting all answers by quizID")
				return
			}

			questionsMap, sortedallAnswers, err := w.deps.Dal.QuestionRepo.GetMapQuestions(ctx, allAnswers)
			if err != nil {
				w.reportError(err, "Error getting questionsMap")
				return
			}

			fmt.Println("ATATATA", questionsMap, sortedallAnswers)

			err = w.processMessageToSMTP(quizConfig, questionsMap, sortedallAnswers, answerContent, answer.CreatedAt)
			if err != nil {
				w.reportError(err, "Error sending message to SMTP")
			}
		}()
	}
}

func (w *RespWorker) processMessageToSMTP(quizConfig model.QuizConfig, questionsMap map[uint64]string,
	allAnswers []model.ResultAnswer, answerContent model.ResultContent, answerTime time.Time) error {
	theme := quizConfig.Mailing.Theme
	quizConfig.Mailing.Theme = quizConfig.Mailing.Reply

	data := senders.TemplateData{
		QuizConfig:    quizConfig.Mailing,
		AnswerContent: answerContent,
		AllAnswers:    allAnswers,
		QuestionsMap:  questionsMap,
	}

	dayOfWeek := wctools.DaysOfWeek[answerTime.Format("Monday")]
	monthOfYear := wctools.MonthsOfYear[answerTime.Format("January")]

	formattedTime := fmt.Sprintf("%s, %d %s %d г., %02d:%02d (UTC%s)",
		dayOfWeek,
		answerTime.Day(),
		monthOfYear,
		answerTime.Year(),
		answerTime.Hour(),
		answerTime.Minute(),
		answerTime.Format("-07:00"),
	)

	data.AnswerTime = formattedTime

	err := w.deps.MailClient.SendMailWithAttachment(answerContent.Email, theme, toClientTemplate, data, nil)
	if err != nil {
		return err
	}

	return nil
}

func (w *RespWorker) reportError(err error, message string) {
	if err != nil {
		fmt.Println(message + ": " + err.Error())
		w.errChan <- err
	}
}
