package client

import (
	"bytes"
	"fmt"
	"gitea.pena/PenaSide/customer/internal/errors"
	"gitea.pena/PenaSide/customer/internal/models"
	"github.com/gofiber/fiber/v2"
	"go.uber.org/zap"
	"mime/multipart"
)

type MailClient struct {
	apiUrl      string
	sender      string
	apiKey      string
	fiberClient *fiber.Client
	logger      *zap.Logger
	mailAddress string
}

func NewMailClient(deps models.MailClientCfg, logger *zap.Logger) *MailClient {
	if deps.FiberClient == nil {
		deps.FiberClient = fiber.AcquireClient()
	}
	return &MailClient{
		apiUrl:      deps.ApiURL,
		sender:      deps.Sender,
		apiKey:      deps.ApiKey,
		fiberClient: deps.FiberClient,
		logger:      logger,
		mailAddress: deps.MailAddress,
	}
}

func (receiver *MailClient) SendMessage(userEmail string, verification *models.Verification, money float32) errors.Error {
	body := fmt.Sprintf("<p>Поступила заявка на оплату через Р/С от пользователя с почтой %s (%s)</p>"+
		"<p>Вот файлы его верификации:</p>"+
		"<p>Запрос на оплату: %f рублей</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.sender,
		"to":      receiver.mailAddress,
		"subject": "Новая заявка на оплату через Р/С",
		"html":    body,
	}

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

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

	fmt.Println("SEEEEEND", receiver.apiUrl)
	req := receiver.fiberClient.Post(receiver.apiUrl).Body(form.Bytes()).ContentType(writer.FormDataContentType())
	if receiver.apiKey != "" {
		req.Set("Authorization", receiver.apiKey)
	}

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

	if statusCode != fiber.StatusOK {
		err := fmt.Errorf("the SMTP service returned an error: %d", statusCode)
		return handleError(receiver.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,
	)
}
