package handlers

import (
	"context"
	"encoding/json"
	"net/http"
	"slices"
	"strings"

	"otaupdate/services"

	"github.com/fiskerinc/cloud-services/pkg/common"
	"github.com/fiskerinc/cloud-services/pkg/logger"
	"github.com/fiskerinc/cloud-services/pkg/loggerdataresp"
	"github.com/fiskerinc/cloud-services/pkg/tmobile"
)

// FIX BUG: current system allows for vins to be tmobile activated,
// but because we don't have them, we don't get them in response list

// HandleCarsAllowedAccess godoc
// @Summary Fetch the list of VINs that can 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>"
// @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/allowed_access [get]
func HandleCarsAllowedAccess(w http.ResponseWriter, r *http.Request) {
	var err error
	res := HandleCarsAllowedAccessResponse{}
	res.AllowedVINs, err = fetchVINList()
	if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
		return
	}
	res.AllowAll = len(res.AllowedVINs) == 0
	err = json.NewEncoder(w).Encode(res)
	loggerdataresp.BadDataErrorResp(w, err, http.StatusInternalServerError)
}

type HandleCarsAllowedAccessResponse struct {
	AllowAll    bool     `json:"allow_all"`
	AllowedVINs []string `json:"allowed_vins"`
}

func fetchVINList() (vins []string, err error) {
	vins, err = services.GetDB().GetCars().GetWhiteListCars()
	
	return
}

// HandleCarsAllowedAccess godoc
// @Summary Check if a single VIN has cloud and t-mobile access
// @Description
// @Accept  json
// @Produce  json
// @Param Authorization header string false "Bearer <ID token>"
// @Param Api-Key header string false "<API token>"
// @Param VINList body HandleAccessCheckInput true "List of VINs to check"
// @Success 200 {object} HandleAccessCheckResponse
// @Failure 400 {object} common.JSONError "Bad request"
// @Failure 401 {object} common.JSONError "Unauthorized"
// @Failure 503 {object} common.JSONError "Service unavailable"
// @Router /cars/allowed_access [post]
func HandleCarAllowedAccess(w http.ResponseWriter, r *http.Request) {
	vinput := HandleAccessCheckInput{}
	err := json.NewDecoder(r.Body).Decode(&vinput)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(err.Error()))
		return
	}
	results, err := CarAllowedAccess(vinput.VINs)

	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		w.Write([]byte(err.Error()))
		return
	}

	res := HandleAccessCheckResponse{
		VINStatuses: results,
	}

	err = json.NewEncoder(w).Encode(res)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(err.Error()))
		return
	}
}

func CarAllowedAccess(vins []string) (results []AllowedStruct, err error) {
	var allowedVINs []string
	allowedVINs, err = fetchVINList()
	if err != nil {
		return
	}
	slices.Sort(allowedVINs)

	carDB := services.GetDB().GetCars()
	tmobileClient, err := tmobile.NewTMobileMiniClient()
	if err != nil {
		return
	}

	results = make([]AllowedStruct, 0, len(vins))
	for _, v := range vins {
		temp := AllowedStruct{}
		temp.VIN = v
		temp.CloudAccess = slices.Contains(allowedVINs, v)
		// Slow but I dont give a damn
		var car *common.Car
		car, err = carDB.SelectByVIN(v)
		if err != nil {
			logger.Err(err).Msg("failed to select car by vin")
		} else if car.ICCID != "" && car.ICCID != "N/A" {
			car.ICCID = strings.TrimSuffix(car.ICCID, "F")
			var details *tmobile.DeviceDetailsResponse
			input := tmobile.DeviceDetailsRequest{
				ICCID: car.ICCID,
			}
			details, err = tmobileClient.DeviceDetails(context.Background(), &input)
			if err != nil {
				break
			}
			temp.TMobileStatus = string(details.Status)
		} else {
			temp.TMobileStatus = "INVALID ICCID"
		}
		results = append(results, temp)
	}

	return
}

type HandleAccessCheckInput struct {
	VINs []string `json:"vins"`
}

type HandleAccessCheckResponse struct {
	VINStatuses []AllowedStruct `json:"vin_statuses"`
}

type AllowedStruct struct {
	VIN           string `json:"vin"`
	CloudAccess   bool   `json:"cloud_access"`
	TMobileStatus string `json:"tmobile_access"`
}
