/*
 * Solidarity Mobility API
 *
 * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
 *
 * API version: 1.0.0
 * Generated by: OpenAPI Generator (https://openapi-generator.tech)
 */

package openapi

import (
	"context"
	"github.com/spf13/viper"
	"net/http"
	"solidarity-service/handler"
	"solidarity-service/internal"
	"solidarity-service/storage"
	"strings"
)

// BookingsFilterAPIService is a service that implements the logic for the BookingsFilterAPIServicer
// This service should implement the business logic for every endpoint for the BookingsFilterAPI API.
// Include any external packages or services that will be required by this service.
type BookingsFilterAPIService struct {
	config  *viper.Viper
	handler *handler.SolidarityServiceHandler
	storage storage.Storage
}

// NewBookingsFilterAPIService creates a default api service
func NewBookingsFilterAPIService(config *viper.Viper, handler *handler.SolidarityServiceHandler, storage storage.Storage) BookingsFilterAPIServicer {
	return &BookingsFilterAPIService{
		config:  config,
		handler: handler,
		storage: storage,
	}
}

// FilterBookingsByStatus - Filter and retrieve bookings by status, type, and ID.
func (s *BookingsFilterAPIService) FilterBookingsByStatus(ctx context.Context, operator string, status string, filterType string, id string) (ImplResponse, error) {
	bookings, err := s.storage.FilterUserBookingsByStatus(filterType, internal.BookingStatus(status), id)
	if err != nil {
		if strings.Contains(err.Error(), " no rows in result set") {
			return Response(http.StatusBadRequest, "no related data recheck your parameters"), nil
		} else {
			return Response(http.StatusInternalServerError, nil), nil
		}
	}
	responses := []Booking{}
	for _, v := range bookings {
		driver, err := s.storage.GetDriver(v.Driver.ID)
		if err != nil {
			return Response(http.StatusInternalServerError, err.Error()), err
		}
		car := driver.Car
		responses = append(responses, Booking{
			Id:     v.ID,
			Status: BookingStatus(v.Status),
			Driver: User{
				Id:               v.Driver.ID,
				Operator:         v.Driver.Operator,
				Alias:            v.Driver.Alias,
				FirstName:        v.Driver.FirstName,
				LastName:         v.Driver.LastName,
				Grade:            int32(v.Driver.Grade),
				Picture:          v.Driver.Picture,
				Gender:           v.Driver.Gender,
				VerifiedIdentity: v.Driver.VerifiedIdentity,
			},
			Passenger: User{
				Id:               v.Passenger.ID,
				Operator:         v.Passenger.Operator,
				Alias:            v.Passenger.Alias,
				FirstName:        v.Passenger.FirstName,
				LastName:         v.Passenger.LastName,
				Grade:            int32(v.Passenger.Grade),
				Picture:          v.Passenger.Picture,
				Gender:           v.Passenger.Gender,
				VerifiedIdentity: v.Passenger.VerifiedIdentity,
			},
			PassengerPickupDate:    int32(v.Pickup_date),
			PassengerPickupLat:     v.PassengerPickupAddress.Point().X(),
			PassengerPickupLng:     v.PassengerPickupAddress.Point().Y(),
			PassengerPickupAddress: v.PassengerPickupAddress.Properties.MustString("name"),
			PassengerDropLat:       v.PassengerDropAddress.Point().X(),
			PassengerDropLng:       v.PassengerDropAddress.Point().Y(),
			PassengerDropAddress:   v.PassengerDropAddress.Properties.MustString("name"),
			Duration:               int32(v.Duration),
			Distance:               int32(v.Distance),
			Car: Car{
				Model: car.Model,
				Brand: car.Brand,
			},
			Price: Price{
				Type: "FREE",
			},
		})
	}

	return Response(200, responses), nil
}
