package server

import (
	"fmt"
	"net/http"
	"strconv"
	"time"

	"github.com/a-h/templ"
	u "github.com/rjNemo/underscore"

	"github.com/rjNemo/rentease/internal/config"
	"github.com/rjNemo/rentease/internal/constant"
	"github.com/rjNemo/rentease/internal/service/booking"
	"github.com/rjNemo/rentease/internal/view"
)

func handleReportsPage() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		monthStr := r.URL.Query().Get("month")
		month, err := strconv.Atoi(monthStr)
		if err != nil || month < 1 || month > 12 {
			month = int(time.Now().Month())
		}

		yearStr := r.URL.Query().Get("year")
		if _, err = strconv.Atoi(yearStr); err != nil {
			yearStr = time.Now().Format("2006")
		}

		component := view.Reports(u.Map(constant.Months, func(m constant.Month) string {
			return string(m)
		}), month, yearStr)

		if err := renderTempl(w, http.StatusOK, component); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}

func handleReportCompute(bs *booking.Service, hc *config.Host) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if err := r.ParseForm(); err != nil {
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		period := r.FormValue("period")
		if !u.Contains([]string{"month", "year"}, period) {
			http.Error(w, fmt.Sprintf("%q is not a valid period", period), http.StatusBadRequest)
			return
		}

		monthStr := r.FormValue("month")
		month, err := strconv.Atoi(monthStr)
		if err != nil || month < 1 || month > 12 {
			http.Error(w, fmt.Sprintf("%q is not a valid month", monthStr), http.StatusBadRequest)
			return
		}

		yearStr := r.FormValue("year")
		year, err := strconv.Atoi(yearStr)
		if err != nil {
			http.Error(w, fmt.Sprintf("%q is not a valid year", yearStr), http.StatusBadRequest)
			return
		}

		report := bs.Report(period, month, year)

		reportVm := &view.ReportViewModel{
			Total:        strconv.FormatFloat(report.Total, 'f', 2, 64),
			PlatformFees: strconv.FormatFloat(report.PlatformFees, 'f', 2, 64),
			Fee:          strconv.FormatFloat(report.Fee, 'f', 2, 64),
			Profit:       strconv.FormatFloat(report.Profit, 'f', 2, 64),
			CardTotal:    strconv.FormatFloat(report.CardTotal, 'f', 2, 64),
			BookingFees:  strconv.FormatFloat(report.BookingFees, 'f', 2, 64),
			PdfUrl:       templ.URL(fmt.Sprintf("%s/pdf?period=%s&month=%d&year=%d", constant.RouteReports, period, month, year)),
			Lines: u.Map(report.Lines, func(l *booking.Line) *view.ReportLine {
				return &view.ReportLine{
					Id:           l.InvoiceNumber(hc),
					Url:          templ.SafeURL(fmt.Sprintf("%s/%d", constant.RouteBooking, l.ID)),
					Total:        strconv.FormatFloat(l.Total, 'f', 2, 64),
					CustomerName: l.CustomerName,
					From:         l.From.Format(time.DateOnly),
					To:           l.To.Format(time.DateOnly),
					Platform:     l.Platform,
					PlatformFees: strconv.FormatFloat(l.PlatformFees, 'f', 2, 64),
					Fee:          strconv.FormatFloat(l.Fee(), 'f', 2, 64),
					Profit:       strconv.FormatFloat(l.Profit(), 'f', 2, 64),
				}
			}),
		}

		if err := renderTempl(w, http.StatusOK, view.ReportSection(reportVm)); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
		}
	}
}
