package lyfthookroute

import (
	"fmt"
	"io/ioutil"
	"strings"
	"sync"
	"time"

	"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
	"bitbucket.org/nemt/nemt-portal-api/application/notificationservice"
	"bitbucket.org/nemt/nemt-portal-api/application/tncservice"
	"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
	"bitbucket.org/nemt/nemt-portal-api/infra/config"
	"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
	"github.com/labstack/echo"
	"github.com/pquerna/ffjson/ffjson"
)

var (
	instance *controller
	once     sync.Once
)

type controller struct {
	cfg          *config.Config
	svc          *applicationservice.Service
	tnc          *tncservice.Service
	notification *notificationservice.Service
}

func controllerInstance(cfg *config.Config, svc *applicationservice.Service, tnc *tncservice.Service, notification *notificationservice.Service) *controller {
	once.Do(func() {
		instance = &controller{
			cfg:          cfg,
			svc:          svc,
			tnc:          tnc,
			notification: notification,
		}
	})
	return instance
}

func (c *controller) handleStateChange(ctx echo.Context) error {
	var rideUUID = ctx.Param("ride_uuid")
	var status = ctx.Param("status")

	user, err := c.svc.Users.GetByUUID("573c70ff-733d-11e7-ba8f-0a6ad3fcdeaa", "")
	if err != nil {
		fmt.Println("Error: ", err.Error())
		return routeutils.HandleAPIError(ctx, err)
	}

	ride, err := c.svc.Rides.GetByUUID(rideUUID, user)
	if err != nil {
		fmt.Println("Error: ", err.Error())
		return routeutils.HandleAPIError(ctx, err)
	}

	authUser, err := c.svc.Users.GetByUUID(ride.CreatedUser.ID, "")
	if err != nil {
		fmt.Println("Error: ", err.Error())
		return routeutils.HandleAPIError(ctx, err)
	}

	// var lyftRide viewmodel.RideRequest
	if authUser.Test {
		_, err = c.tnc.Lyft.GetRideStatus(viewmodel.RideRequest{RideID: ride.InternalID}, status)
		go func() {
			secondCall := func() {
				ride.InternalID = "s_" + ride.InternalID
				c.tnc.Lyft.GetRideStatus(viewmodel.RideRequest{RideID: ride.InternalID}, status)
			}
			time.AfterFunc(1*time.Second, secondCall)
		}()
	} else {
		_, err = c.tnc.LyftProd.GetRideDetails(viewmodel.RideRequest{RideID: ride.InternalID})
	}
	if err != nil {
		return routeutils.HandleAPIError(ctx, err)
	}

	// if ride.Route.ETA ==

	// UUID, _ := uuid.NewV4()
	// hook := viewmodel.WebhookResponse{
	// 	Event:      lyftRide,
	// 	EventID:    UUID.String(),
	// 	EventType:  "ride.status.updated",
	// 	HREF:       "Test",
	// 	OccurredAt: time.Now().UTC().Format("2006-01-02T15:04:05-0700"),
	// }

	// ride, err = c.svc.Rides.Update(hook)
	// if err != nil {
	// 	fmt.Println("Error: ", err.Error())
	// 	return routeutils.HandleAPIError(ctx, err)
	// }

	// lyftRide.Driver.FirstName = ride.Driver.FirstName
	// lyftRide.Driver.LastName = ride.Driver.LastName
	// lyftRide.Status = ride.Status.Key
	// lyftRide.Vehicle.Color = ride.Vehicle.Color
	// lyftRide.Vehicle.LicensePlate = ride.Vehicle.LicensePlate
	// lyftRide.Vehicle.Make = ride.Vehicle.Make
	// lyftRide.Vehicle.Model = ride.Vehicle.Model
	// lyftRide.Destination.ETASeconds = &ride.Route.ETA
	// if lyftRide.Status == "canceled" {
	// 	lyftRide.CanceledBy = "driver"
	// }

	// if ride.Status.Key == "accepted" || ride.Status.Key == "pickedUp" || ride.Status.Key == "arrived" {
	// 	ride.Route.Location = ride.Route.Origin
	// 	ride.Route.Location.Address = ""
	// 	ride.Route.Location.Name = ""

	// 	switch ride.Status.Key {
	// 	case "accepted":
	// 		if lyftRide.Origin.ETASeconds != nil {
	// 			ride.Route.ETA = *lyftRide.Origin.ETASeconds
	// 		} else {
	// 			ride.Route.ETA = 0
	// 			if c.cfg.App.Debug {
	// 				ride.Route.ETA = 350
	// 			}
	// 		}
	// 	case "pickedUp":
	// 	case "arrived":
	// 		if lyftRide.Destination.ETASeconds != nil {
	// 			ride.Route.ETA = *lyftRide.Destination.ETASeconds
	// 		} else {
	// 			ride.Route.ETA = 0
	// 			if c.cfg.App.Debug {
	// 				ride.Route.ETA = 350
	// 			}
	// 		}
	// 	}

	// 	if lyftRide.Location.Latitude != 0 && lyftRide.Location.Longitude != 0 {
	// 		ride.Route.Location.Latitude = lyftRide.Location.Latitude
	// 		ride.Route.Location.Longitude = lyftRide.Location.Longitude
	// 		ride.Route.Location.Bearing = lyftRide.Location.Bearing
	// 	}
	// }

	// err = c.svc.Notification.SendNotification(status, ride, lyftRide)
	// if err != nil {
	// 	fmt.Println("Error: ", err.Error())
	// 	return routeutils.HandleAPIError(ctx, err)
	// }

	return routeutils.ResponseAPIOK(ctx, ride)
}

func (c *controller) handle(ctx echo.Context) error {
	fmt.Println("RECEIVING HOOK: ")
	body, err := ioutil.ReadAll(ctx.Request().Body)
	if err != nil {
		fmt.Println("Error to read the body of the webhook: ", err.Error())
	} else {
		fmt.Println(string(body))
	}

	var requestRide viewmodel.WebhookResponse
	err = ffjson.Unmarshal(body, &requestRide)
	if err != nil {
		fmt.Println(err)
		return routeutils.ResponseAPIValidationError(ctx, "invalid parameters")
	}
	defer ctx.Request().Body.Close()
	// err = ctx.Bind(&requestRide)
	// if err != nil {
	// 	fmt.Println(err)
	// 	return routeutils.ResponseAPIValidationError(ctx, "invalid parameters")
	// }

	requestRide.Event.RideID = strings.Replace(requestRide.Event.RideID, "s_", "", -1)
	requestRide.Event.RideID = strings.Replace(requestRide.Event.RideID, "sandboxevent-", "", -1)

	ride, err := c.svc.Rides.Update(requestRide)
	if err != nil {
		fmt.Println("Error: ", err.Error())
		return routeutils.HandleAPIError(ctx, err)
	}

	switch requestRide.EventType {
	case "ride.status.updated":
		go func() {
			if err := c.svc.Notification.SendNotification(requestRide.Event.Status, ride, requestRide.Event); err != nil {
				fmt.Println("Error: ", err.Error())
			}
		}()
	default:
		fmt.Println(requestRide.EventType, " :", requestRide.Event.Status)
	}

	ctx.Response().Header().Set("Content-Type", "application/json")
	return routeutils.ResponseAPIOK(ctx, ride)
}
