package auth

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"

	"github.com/AlchemyTelcoSolutions/callisto-so-bff/cmd/app/config"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/internal/domain/model"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/internal/proxy"
	"github.com/AlchemyTelcoSolutions/xutils-go/xlogger"
	"go.uber.org/zap"
)

func NewAuthService() *Service {
	return &Service{}
}

// SetLogger is a setter for logger
func (s *Service) SetLogger(l xlogger.Logger) *Service {
	s.logger = l
	return s
}

// SetConfigs is a setter for Configs
func (s *Service) SetConfigs(c config.AppConfig) *Service {
	s.configs = c
	return s
}

// SetProxyService SetCallistoAPiClient is a setter for callisto api client
func (s *Service) SetProxyService(h proxy.ProxyService) *Service {
	s.httpProxySvc = h
	return s
}

// AuthMeByRequest is a function that get auth /me to callisto-api
func (s *Service) AuthMeByRequest(req *http.Request) (*model.AuthMeResponse, error) {
	// get auth me endpoint
	cfg := s.configs.GetConfigurations().CallistoAPI
	authMe := strings.Join([]string{cfg.Host, cfg.Auth.Me}, "")

	resp, err := s.httpProxySvc.SendRequestToClient(req, authMe, map[string]string{})
	if err != nil {
		s.logger.Error("error sending request to callisto-api", err, zap.Any("request", req))
		return nil, fmt.Errorf("error sending request auth/me to callisto-api: %v", err)
	}

	if err != nil || resp.StatusCode < http.StatusOK || resp.StatusCode > 299 {
		s.logger.Warning("api call to callisto-api auth/me not returning success", zap.Any("response", resp))
		return nil, fmt.Errorf("callisto-api call to auth/me not returning success, receive this code: %v with response: %v", resp.StatusCode, resp.BodyBytes)
	}

	authResp := &model.AuthMeResponse{}

	// try to unmarshall the reponse from callisto-api bff endpoint
	if err = json.Unmarshal(resp.BodyBytes, authResp); err != nil {
		return nil, fmt.Errorf("failed to unmarshall response %s", string(resp.BodyBytes[:]))
	}

	return authResp, nil
}
