package httpinvoce

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"

	"git.schreifuchs.ch/lou-taylor/accounting/internal/email"
)

const bufSize = 1024 * 1024 // 1Mib

func (s Service) createInvoice(w http.ResponseWriter, r *http.Request) {
	var req invoiceReq

	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		s.sendErr(w, http.StatusBadRequest, "cannot read body")
		return
	}

	repos, err := req.GetRepos()
	if err != nil {
		s.sendErr(w, http.StatusInternalServerError, "cannot get repos")
		return
	}

	invoice, report, err := s.invoice.Generate(req.Creditor, &req.Debtor, time.Duration(req.DurationThreshold), req.HourlyRate, repos)
	if err != nil {
		s.sendErr(w, http.StatusInternalServerError, "internal server error")
		return
	}
	// if no time has to be billed aka if bill for 0 CHF
	if report.Total() <= time.Duration(0) {
		s.sendErrf(w, http.StatusNotFound, "no suitable issues to be billed")
		return
	}

	w.Header().Set("Content-type", "application/pdf")
	w.Header().Set(
		"Content-Disposition",
		fmt.Sprintf("attachment; filename=\"%s\"", invoiceName()),
	)

	_, err = io.Copy(w, invoice)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		return
	}
}

func (s Service) sendInvoice(w http.ResponseWriter, r *http.Request) {
	var req sendReq
	err := json.NewDecoder(r.Body).Decode(&req)
	if err != nil {
		s.sendErrf(w, http.StatusBadRequest, "cannot read body: %v", err)
		return
	}

	repos, err := req.Invoice.GetRepos()
	if err != nil {
		s.sendErr(w, 500, err.Error())
		return
	}
	invoice, report, err := s.invoice.Generate(req.Invoice.Creditor, &req.Invoice.Debtor, time.Duration(req.Invoice.DurationThreshold), req.Invoice.HourlyRate, repos)
	if err != nil {
		s.sendErr(w, http.StatusInternalServerError, "error while processing invoice:", err)
		return
	}
	// if no time has to be billed aka if bill for 0 CHF
	if report.Total() <= time.Duration(0) {
		s.sendErr(w, http.StatusNotFound, "no suitable issues to be billed")
		return
	}

	invoiceData, err := io.ReadAll(invoice)
	if err != nil {
		s.sendErrf(w, http.StatusInternalServerError, "error while creating pdf: %v", err)
		return
	}

	mail := req.ToEMail()
	mail.Attachments = append(mail.Attachments, email.Attachment{
		Name:     invoiceName(),
		MimeType: "application/pdf",
		Content:  bytes.NewReader(invoiceData),
	})

	err = s.mail.Send(mail)
	if err != nil {
		s.sendErrf(w, http.StatusInternalServerError, "error while sending mail: %v", err)
		return
	}

	_, err = w.Write(invoiceData)
	if err != nil {
		s.sendErr(w, http.StatusInternalServerError, "")
	}
}

func invoiceName() string {
	return fmt.Sprintf("%s_invoice.pdf", time.Now().Format("20060102"))
}
