package client

import (
	commonAPI "code.secondbit.org/api.hg"
	"code.secondbit.org/auth.hg"

	"code.secondbit.org/ducky/subscriptions.hg"
	"code.secondbit.org/ducky/subscriptions.hg/api"
)

// CreateSubscription creates a Subscription using the passed SubscriptionChange.
// It returns the created Subscription on success. It returns ErrSubscriptionAlreadyExists
// if a subscription already exists for that user. It returns ErrStripeSubscriptionAlreadyExists
// if that Stripe subscription is already associated with a user. It returns an
// ErrSubscriptionNotFound if no Subscription is returned in the response, which generally denotes
// a server error.
func (c *Client) CreateSubscription(change subscriptions.SubscriptionChange) (subscriptions.Subscription, error) {
	resp, err := c.Post("/subscriptions/", change, auth.Scopes{api.ScopeSubscription, api.ScopeSubscriptionAdmin}.Strings(), change.UserID)
	if err != nil {
		hErr, ok := err.(httpErrors)
		if ok {
			for _, e := range hErr {
				if e.Slug == commonAPI.RequestErrConflict &&
					e.Field == "/user_id" {
					return subscriptions.Subscription{}, subscriptions.ErrSubscriptionAlreadyExists
				} else if e.Slug == commonAPI.RequestErrConflict &&
					e.Field == "/stripe_token" {
					return subscriptions.Subscription{}, subscriptions.ErrStripeSubscriptionAlreadyExists
				}
			}
		}
		return subscriptions.Subscription{}, err
	}
	if len(resp.Subscriptions) < 1 {
		return subscriptions.Subscription{}, subscriptions.ErrSubscriptionNotFound
	}
	return resp.Subscriptions[0], nil
}

// UpdateSubscription applies the passed SubscriptionChange to the API. It returns
// the update Subscription on success. It returns an ErrSubscriptionNotFound if no
// subscription is returned in the response, which generall denotes a server error.
func (c *Client) UpdateSubscription(change subscriptions.SubscriptionChange) (subscriptions.Subscription, error) {
	resp, err := c.Patch("/subscriptions/"+change.UserID.String(), change, auth.Scopes{api.ScopeSubscription, api.ScopeSubscriptionAdmin}.Strings(), change.UserID)
	if err != nil {
		// BUG(paddy): We need to handle and gracefully return errors raised by the API.
		return subscriptions.Subscription{}, err
	}
	if len(resp.Subscriptions) < 1 {
		return subscriptions.Subscription{}, subscriptions.ErrSubscriptionNotFound
	}
	return resp.Subscriptions[0], nil
}
