package booking

import (
	"log"
	"strconv"
	"time"

	u "github.com/rjNemo/underscore"

	"github.com/rjNemo/rentease/internal/config"
	"github.com/rjNemo/rentease/internal/constant"
)

var hc = config.NewHost()

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

type ReportData struct {
	Month        string
	Year         int
	Total        string
	PlatformFees string
	Fee          string
	Profit       string
	CardTotal    string
	BookingFees  string
	Lines        []ReportLine
}

type ReportLine struct {
	InvoiceNumber string
	CustomerName  string
	From          string
	To            string
	Total         string
	Platform      string
	PlatformFees  string
	Fee           string
	Profit        string
}

func (r Report) Data(month, year int) ReportData {
	return ReportData{
		Month:        constant.Months[month-1].ToFrench(),
		Year:         year,
		Total:        strconv.FormatFloat(r.Total, 'f', 2, 64),
		PlatformFees: strconv.FormatFloat(r.PlatformFees, 'f', 2, 64),
		Fee:          strconv.FormatFloat(r.Fee, 'f', 2, 64),
		Profit:       strconv.FormatFloat(r.Profit, 'f', 2, 64),
		CardTotal:    strconv.FormatFloat(r.CardTotal, 'f', 2, 64),
		BookingFees:  strconv.FormatFloat(r.BookingFees, 'f', 2, 64),
		Lines: u.Map(r.Lines, func(l *Line) ReportLine {
			return ReportLine{
				InvoiceNumber: l.InvoiceNumber(hc),
				CustomerName:  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,
				PlatformFees:  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) (string, error) {
	return bs.pdf.BuildReport(report.Data(month, year), period, month, year)
}
