package handlers

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"otaupdate/services"

	"github.com/fiskerinc/cloud-services/pkg/loggerdataresp"
	"github.com/fiskerinc/cloud-services/pkg/tmobile"
	"github.com/fiskerinc/cloud-services/pkg/vindecoder"
	"github.com/pkg/errors"
)

// HandleCarChangeAccess godoc
// @Summary change access for a vin to connect to fisker cloud
// @Description Note: when a VIN is added or removed, changes will take time to propagate to the network filters
// @Accept  json
// @Produce  json
// @Param Authorization header string false "Bearer <ID token>"
// @Param Api-Key header string false "<API token>"
// @Param data body CarChangeAccessInput true "car change access data"
// @Success 200 {object} HandleCarsAllowedAccessResponse
// @Failure 400 {object} common.JSONError "Bad request"
// @Failure 401 {object} common.JSONError "Unauthorized"
// @Failure 503 {object} common.JSONError "Service unavailable"
// @Router /cars/change_access [post]
func HandleCarChangeAccess(w http.ResponseWriter, r *http.Request) {
	ccai := CarChangeAccessInput{}
	err := json.NewDecoder(r.Body).Decode(&ccai)
	if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
		return
	}

	failedVINs := []string{}
	for _, vin := range ccai.VINs {
		ok := vindecoder.ValidateVINSimple(vin)
		if !ok {
			failedVINs = append(failedVINs, vin)
		}
	}
	if len(failedVINs) > 0 {
		errors.New(fmt.Sprintf("VINS Invalid, no changes made: %+v", failedVINs))
		loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest)
		return
	}

	err = CarChangeAccess(ccai)
	if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
		return
	}
}

func CarChangeAccess(ccai CarChangeAccessInput) (err error) {
	// Add/Remove from the database
	if ccai.AllowCloudAccess != nil {
		if *ccai.AllowCloudAccess {
			err = services.GetDB().GetCars().WhitelistCars(ccai.VINs, ccai.Source)
			if err != nil {
				return err
			}
		} else {
			err = services.GetDB().GetCars().BlacklistCars(ccai.VINs)
			if err != nil {
				return err
			}
		}
	}

	if ccai.AllowTMobileAccess != nil {
		var miniClient *tmobile.TMobileMiniClient
		miniClient, err = tmobile.NewTMobileMiniClient()
		if err != nil {
			return errors.WithMessage(err, "Failed to Create TMOible Client")
		}

		var iccids []string
		iccids, err = services.GetDB().GetCars().GetICCIDs(ccai.VINs)
		if err != nil {
			return errors.WithMessage(err, "Failed to get ICCIDs")
		}
		tmobileInput := tmobile.ChangeDeviceActivation{
			ICCIDs:  iccids,
			Enabled: *ccai.AllowTMobileAccess,
		}

		// Add/Remove from TMobile
		// TODO when T-Mobile gets back about access
		err = miniClient.ChangeDeviceStatus(context.Background(), tmobileInput)
		if err != nil {
			return
		}
	}

	return
}

type CarChangeAccessInput struct {
	VINs               []string `json:"vins"`                           // List of VINs that will be changed
	AllowCloudAccess   *bool    `json:"allow_cloud_access,omitempty"`   // Cars can connect through gateway
	AllowTMobileAccess *bool    `json:"allow_tmobile_access,omitempty"` // Cars get tmobile access
	Source             string   `json:"source,omitempty"`
}
