package booking

import (
	"log"
	"strconv"
	"time"

	u "github.com/rjNemo/underscore"
)

type Report struct {
	Lines        []*Line
	Total        float64
	PlatformFees float64
	Fee          float64
	Profit       float64
	CardTotal    float64
	BookingFees  float64
}

func (r Report) Serialize(month, year int) map[string]any {
	return map[string]any{
		"month":         month,
		"year":          year,
		"total":         strconv.FormatFloat(r.Total, 'f', 2, 64),
		"platform_fees": strconv.FormatFloat(r.PlatformFees, 'f', 2, 64),
		"fee":           strconv.FormatFloat(r.Fee, 'f', 2, 64),
		"profit":        strconv.FormatFloat(r.Profit, 'f', 2, 64),
		"card_total":    strconv.FormatFloat(r.CardTotal, 'f', 2, 64),
		"booking_fees":  strconv.FormatFloat(r.BookingFees, 'f', 2, 64),
		"lines": u.Map(r.Lines, func(l *Line) map[string]any {
			return map[string]any{
				"id":            l.Id,
				"name":          l.CustomerName,
				"from":          l.From.Format("02/01/2006"),
				"to":            l.To.Format("02/01/2006"),
				"total":         strconv.FormatFloat(l.Total, 'f', 2, 64),
				"platform":      l.Platform,
				"platform_fees": strconv.FormatFloat(l.PlatformFees, 'f', 2, 64),
				"fee":           strconv.FormatFloat(l.Fee(), 'f', 2, 64),
				"profit":        strconv.FormatFloat(l.Profit(), 'f', 2, 64),
			}
		}),
	}
}

func (bs Service) Report(period string, month, year int) *Report {
	var startDate time.Time
	var endDate time.Time

	if period == "month" {
		startDate = time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
		endDate = time.Date(year, time.Month(month)+1, 1, 0, 0, 0, 0, time.UTC).Add(-24 * time.Hour)
	} else {
		startDate = time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC)
		endDate = time.Date(year, time.December, 31, 0, 0, 0, 0, time.UTC)
	}

	lines, err := bs.store.List(startDate, endDate)
	if err != nil {
		log.Println(err)
	}

	cardTotal, err := bs.store.CardTotal(startDate, endDate)
	if err != nil {
		log.Println(err)
	}

	return &Report{
		Total:        u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.Total }, 0.0),
		PlatformFees: u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.PlatformFees }, 0.0),
		Fee:          u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.Fee() }, 0.0),
		Profit:       u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.Profit() }, 0.0),
		Lines:        lines,
		CardTotal:    cardTotal,
		BookingFees: u.Reduce(lines, func(l *Line, sum float64) float64 {
			if l.Platform == "Booking" {
				return sum + l.PlatformFees
			}
			return sum
		}, 0.0),
	}
}

func (bs Service) BuildReport(report *Report, period string, month, year int) error {
	return bs.pdf.BuildReport(report.Serialize(month, year), period, month, year)
}
