package client

import (
	"bytes"
	"fmt"
	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"
	"mime/multipart"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)

type MailClientDeps struct {
	ApiUrl      string
	Sender      string
	Auth        *models.PlainAuth
	ApiKey      string
	FiberClient *fiber.Client
	Logger      *zap.Logger
	MailAddress string
}

type MailClient struct {
	deps MailClientDeps
}

func NewMailClient(deps MailClientDeps) *MailClient {
	if deps.FiberClient == nil {
		deps.FiberClient = fiber.AcquireClient()
	}
	return &MailClient{
		deps: deps,
	}
}

func (receiver *MailClient) SendMessage(userEmail string, verification *models.Verification, money float32) errors.Error {
	body := fmt.Sprintf("<p>Поступила заявка на оплату через Р/С от пользователя с почтой %s (%s)</p>"+
		"<p>Вот файлы его верификации:</p>"+
		"<p>Запрос на оплату: %d рублей</p>", userEmail, verification.UserID, money)

	for _, file := range verification.Files {
		body += fmt.Sprintf("<p>%s: <a href=\"%s\">%s</a></p>", file.Name, file.URL, file.URL)
	}

	form := new(bytes.Buffer)
	writer := multipart.NewWriter(form)
	defer writer.Close()

	fields := map[string]string{
		"from":    receiver.deps.Sender,
		"to":      receiver.deps.MailAddress,
		"subject": "Новая заявка на оплату через Р/С",
		"html":    body,
	}

	for key, value := range fields {
		if err := writer.WriteField(key, value); err != nil {
			return handleError(receiver.deps.Logger, "Error writing form field", err)
		}
	}

	if err := writer.Close(); err != nil {
		return handleError(receiver.deps.Logger, "Error closing form writer", err)
	}

	fmt.Println("SEEEEEND", receiver.deps.ApiUrl)
	req := receiver.deps.FiberClient.Post(receiver.deps.ApiUrl).Body(form.Bytes()).ContentType(writer.FormDataContentType())
	if receiver.deps.ApiKey != "" {
		req.Set("Authorization", receiver.deps.ApiKey)
	}

	statusCode, _, errs := req.Bytes()
	if errs != nil {
		return handleError(receiver.deps.Logger, "Error sending request", errs[0])
	}

	if statusCode != fiber.StatusOK {
		err := fmt.Errorf("the SMTP service returned an error: %s", statusCode)
		return handleError(receiver.deps.Logger, "Error sending email", err)
	}

	return nil
}

func handleError(logger *zap.Logger, message string, err error) errors.Error {
	logger.Error(message, zap.Error(err))
	return errors.New(
		fmt.Errorf("failed to send email on <SendMessage> of <MailClient>: %w", err),
		errors.ErrInternalError,
	)
}
