package contact

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/dchest/captcha"
	"gopkg.in/gomail.v2"
	"net/http"
	"netoik.io/netoik-website/pkg/api"
	"netoik.io/netoik-website/pkg/conf"
	"os"
	"path/filepath"
)

type request struct {
	Name          string `json:"name"`
	Email         string `json:"email"`
	Phone         string `json:"phone"`
	Company       string `json:"company"`
	Message       string `json:"message"`
	CaptchaId     string `json:"captchaId"`
	CaptchaDigits string `json:"captchaDigits"`
}

func HandleSend(w http.ResponseWriter, r *http.Request) {
	// Check method
	if r.Method != "POST" {
		api.Reply(w, 405, api.Answer{})
		return
	}

	// Parse json from request body
	var data request
	if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
		api.Reply(w, 400, api.Answer{})
		return
	}
	if data.Name == "" || len(data.Name) > 200 {
		api.Reply(w, 400, api.Answer{})
		return
	}
	if data.Email == "" || len(data.Email) > 200 {
		api.Reply(w, 400, api.Answer{})
		return
	}
	if len(data.Phone) > 200 {
		api.Reply(w, 400, api.Answer{})
		return
	}
	if len(data.Company) > 200 {
		api.Reply(w, 400, api.Answer{})
		return
	}
	if data.Message == "" || len(data.Message) > 10000 {
		api.Reply(w, 400, api.Answer{})
		return
	}
	if data.CaptchaId == "" {
		api.Reply(w, 400, api.Answer{})
		return
	}
	if data.CaptchaDigits == "" {
		api.Reply(w, 400, api.Answer{})
		return
	}

	// Check captcha digits
	if !captcha.VerifyString(data.CaptchaId, data.CaptchaDigits) {
		api.Reply(w, 418, api.Answer{})
		return
	}

	// Captcha has been verified, so remove image
	path := filepath.Join(conf.Conf.CaptchaDirectory, data.CaptchaId+".png")
	if err := os.Remove(path); err != nil && !errors.Is(err, os.ErrNotExist) {
		fmt.Fprintf(os.Stderr, "ERROR: cannot remove captcha image %q: %s", path, err.Error())
	}

	// Build email
	msg := gomail.NewMessage()
	msg.SetHeader("From", conf.Conf.SMTPUsername)
	msg.SetHeader("To", conf.Conf.SMTPReceiver)
	msg.SetHeader("Subject", "Message from www.netoik.io")
	msg.SetBody("text/plain", fmt.Sprintf(
		"You have received a message from frontend.\nname: %s\nemail: %s\nphone: %s\ncompany: %s\n%s",
		data.Name, data.Email, data.Phone, data.Company, data.Message))

	// Configure SMTP dialer and send email
	dialer := gomail.NewDialer(conf.Conf.SMTPHost, conf.Conf.SMTPPort, conf.Conf.SMTPUsername, conf.Conf.SMTPPassword)
	if err := dialer.DialAndSend(msg); err != nil {
		fmt.Fprintf(os.Stderr, "cannot send email: %s\n", err.Error())
		api.Reply(w, 400, api.Answer{})
		return
	}
	api.Reply(w, 200, api.Answer{Success: true})
}
