package profileroute

import (
	"sync"

	"bitbucket.org/nemt/nemt-portal-api/application/applicationservice"
	"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
	"bitbucket.org/nemt/nemt-portal-api/domain"
	"bitbucket.org/nemt/nemt-portal-api/infra/cache"
	"bitbucket.org/nemt/nemt-portal-api/infra/config"
	"bitbucket.org/nemt/nemt-portal-api/server/router/routeutils"
	"github.com/labstack/echo"
)

var (
	instance *controller
	once     sync.Once
)

type controller struct {
	cfg *config.Config
	svc *applicationservice.Service
}

func controllerInstance(cfg *config.Config, svc *applicationservice.Service) *controller {
	once.Do(func() {
		instance = &controller{
			cfg: cfg,
			svc: svc,
		}
	})

	return instance
}

func (c *controller) handle(ctx echo.Context) error {

	cache := cache.Instance(c.cfg)
	cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
	resp := []viewmodel.Profile{}
	err := cache.GetStruct(cacheKey, &resp)
	if err != nil {
		if err != domain.ErrCacheMiss {
			ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
		}
		resp, err = c.svc.Profile.GetVisibles(true)
		if err != nil {
			return routeutils.HandleAPIError(ctx, err)
		}
		cache.SetStruct(cacheKey, resp)
	}
	return routeutils.ResponseAPIOK(ctx, resp)
}

func (c *controller) handleKey(ctx echo.Context) error {

	key, err := routeutils.GetAndValidateStringParam(ctx, "key", "Key is mandatory")
	if err != nil {
		return routeutils.HandleAPIError(ctx, err)
	}

	cache := cache.Instance(c.cfg)
	cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
	resp := viewmodel.Profile{}

	err = cache.GetStruct(cacheKey, &resp)
	if err != nil {
		if err != domain.ErrCacheMiss {
			ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
		}
		resp, err = c.svc.Profile.GetByKey(key)
		if err != nil {
			return routeutils.HandleAPIError(ctx, err)
		}
		cache.SetStruct(cacheKey, resp)
	}

	return routeutils.ResponseAPIOK(ctx, resp)
}

func (c *controller) handleOrg(ctx echo.Context) error {
	orgType, err := routeutils.GetAndValidateStringParam(ctx, "org_key", "Org is mandatory")
	if err != nil {
		return routeutils.HandleAPIError(ctx, err)
	}

	cache := cache.Instance(c.cfg)
	cacheKey := ctx.Request().Method + ctx.Request().URL.EscapedPath() + ctx.Request().URL.RawQuery
	resp := []viewmodel.Profile{}
	err = cache.GetStruct(cacheKey, &resp)
	if err != nil {
		if err != domain.ErrCacheMiss {
			ctx.Logger().Errorf(domain.LogProblemGettingFromCache, err)
		}
		resp, err = c.svc.Profile.GetByOrganizationType(orgType)
		if err != nil {
			return routeutils.HandleAPIError(ctx, err)
		}
		cache.SetStruct(cacheKey, resp)
	}

	return routeutils.ResponseAPIOK(ctx, resp)
}
