package client

import (
	"context"
	"fmt"
	"log"
	"net/url"

	"go.uber.org/zap"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/utils"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/client"
)

type HubadminClientDeps struct {
	Logger *zap.Logger
	URLs   *models.HubadminMicroserviceURL
}

type HubadminClient struct {
	logger *zap.Logger
	urls   *models.HubadminMicroserviceURL
}

func NewHubadminClient(deps HubadminClientDeps) *HubadminClient {
	if deps.Logger == nil {
		log.Panicln("logger is nil on <NewHubadminClient>")
	}

	if deps.URLs == nil {
		log.Panicln("urls is nil on <NewHubadminClient>")
	}

	return &HubadminClient{
		logger: deps.Logger,
		urls:   deps.URLs,
	}
}

func (receiver *HubadminClient) GetTariff(ctx context.Context, accessToken string, tariffID string) (*models.Tariff, errors.Error) {
	tariffURL, err := url.JoinPath(receiver.urls.Tariff, tariffID)
	if err != nil {
		return nil, errors.New(fmt.Errorf("failed to join path on <GetTariff> of <HubadminClient>: %w", err), errors.ErrInternalError)
	}

	response, err := client.Get[models.Tariff, models.FastifyError](ctx, &client.RequestSettings{
		URL: tariffURL,
		Headers: map[string]string{
			"Content-Type":  "application/json",
			"Authorization": fmt.Sprintf("Bearer %s", accessToken),
		},
	})
	if err != nil {
		receiver.logger.Error("failed to request get tariff on <GetTariff> of <HubadminClient>",
			zap.Error(err),
			zap.String("tariffID", tariffID),
		)

		return nil, errors.New(
			fmt.Errorf("failed to request get tariff with <%s> on <GetTariff> of <HubadminClient>: %w", tariffID, err),
			errors.ErrInternalError,
		)
	}
	if response.Error != nil {
		receiver.logger.Error("failed request on <GetTariff> of <HubadminClient>",
			zap.String("error", response.Error.Message),
			zap.String("tariffID", tariffID),
		)

		return nil, errors.New(
			fmt.Errorf("failed request with <%s> on <GetTariff> of <HubadminClient>: %s", tariffID, response.Error.Message),
			utils.DetermineClientErrorResponse(response.StatusCode),
		)
	}

	return response.Body, nil
}

func (receiver *HubadminClient) GetTariffs(ctx context.Context, accessToken string, tarriffIDs []string) ([]models.Tariff, errors.Error) {
	tariffs := make([]models.Tariff, len(tarriffIDs))

	for index, tariffID := range tarriffIDs {
		tariff, err := receiver.GetTariff(ctx, accessToken, tariffID)
		if err != nil {
			receiver.logger.Error("failed to get tariff on <GetTariffs> of <HubadminClient>", zap.Error(err), zap.String("tariffID", tariffID))
			return []models.Tariff{}, err
		}

		tariffs[index] = *tariff
	}

	return tariffs, nil
}
