package service

import (
	"sort"
	"time"

	"hammond/common"
	"hammond/db"
	"hammond/models"
)

func GetMileageByVehicleId(vehicleId string, since time.Time, mileageOption string) (mileage []models.MileageModel, err error) {
	data, err := db.GetFillupsByVehicleIdSince(vehicleId, since)
	if err != nil {
		return nil, err
	}

	fillups := make([]db.Fillup, len(*data))
	copy(fillups, *data)
	sort.Slice(fillups, func(i, j int) bool {
		return fillups[i].OdoReading > fillups[j].OdoReading
	})

	var mileages []models.MileageModel

	for i := 0; i < len(fillups)-1; i++ {
		last := i + 1

		currentFillup := fillups[i]
		lastFillup := fillups[last]

		mileage := models.MileageModel{
			Date:         currentFillup.Date,
			VehicleID:    currentFillup.VehicleID,
			FuelUnit:     currentFillup.FuelUnit,
			FuelQuantity: currentFillup.FuelQuantity,
			PerUnitPrice: currentFillup.PerUnitPrice,
			OdoReading:   currentFillup.OdoReading,
			Currency:     currentFillup.Currency,
			DistanceUnit: currentFillup.DistanceUnit,
			Mileage:      0,
			CostPerMile:  0,
		}

		if currentFillup.IsTankFull != nil && *currentFillup.IsTankFull && (currentFillup.HasMissedFillup == nil || !(*currentFillup.HasMissedFillup)) {
			currentOdoReading := float32(currentFillup.OdoReading);
			lastFillupOdoReading := float32(lastFillup.OdoReading);
			currentFuelQuantity := float32(currentFillup.FuelQuantity);
			// If miles per gallon option and distanceUnit is km, convert from km to miles 
			// 	then check if fuel unit is litres. If it is, convert to gallons
			if (mileageOption == "mpg" && mileage.DistanceUnit == db.KILOMETERS) {
				currentOdoReading = common.KmToMiles(currentOdoReading);
				lastFillupOdoReading = common.KmToMiles(lastFillupOdoReading);
				if (mileage.FuelUnit == db.LITRE) {
					currentFuelQuantity = common.LitreToGallon(currentFuelQuantity);
				}
			}

			// If km_litre option or litre per 100km and distanceUnit is miles, convert from miles to km 
			// 	then check if fuel unit is not litres. If it isn't, convert to litres

			if ((mileageOption == "km_litre" || mileageOption == "litre_100km") && mileage.DistanceUnit == db.MILES) {
				currentOdoReading = common.MilesToKm(currentOdoReading);
				lastFillupOdoReading = common.MilesToKm(lastFillupOdoReading);

				if (mileage.FuelUnit == db.US_GALLON) {
					currentFuelQuantity = common.GallonToLitre(currentFuelQuantity);
				}
			} 

			


			distance := float32(currentOdoReading - lastFillupOdoReading);
			if (mileageOption == "litre_100km") {
				mileage.Mileage = currentFuelQuantity / distance * 100;
			} else {
				mileage.Mileage = distance / currentFuelQuantity;
			}

			mileage.CostPerMile = distance / currentFillup.TotalAmount;

		}

		mileages = append(mileages, mileage)
	}
	if mileages == nil {
		mileages = make([]models.MileageModel, 0)
	}
	return mileages, nil
}
