//go:build enterprise

/*
Copyright (c) Edgeless Systems GmbH

SPDX-License-Identifier: AGPL-3.0-only
*/

package license

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"

	"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
)

const (
	apiHost     = "license.confidential.cloud"
	licensePath = "api/v1/license"
)

// Checker checks the Constellation license.
type Checker struct {
	httpClient *http.Client
}

// NewChecker creates a new Checker.
func NewChecker() *Checker {
	return &Checker{
		httpClient: http.DefaultClient,
	}
}

// CheckLicense checks the Constellation license. If the license is valid, it returns the vCPU quota.
func (c *Checker) CheckLicense(ctx context.Context, csp cloudprovider.Provider, action Action, licenseID string) (int, error) {
	checkRequest := quotaCheckRequest{
		Provider: csp.String(),
		License:  licenseID,
		Action:   action,
	}

	reqBody, err := json.Marshal(checkRequest)
	if err != nil {
		return 0, fmt.Errorf("unable to marshal input: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, licenseURL().String(), bytes.NewBuffer(reqBody))
	if err != nil {
		return 0, fmt.Errorf("unable to create request: %w", err)
	}
	resp, err := c.httpClient.Do(req)
	if err != nil {
		return 0, fmt.Errorf("unable to do request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return 0, fmt.Errorf("http error %d", resp.StatusCode)
	}

	responseContentType := resp.Header.Get("Content-Type")
	if responseContentType != "application/json" {
		return 0, fmt.Errorf("expected server JSON response but got '%s'", responseContentType)
	}

	var parsedResponse quotaCheckResponse
	err = json.NewDecoder(resp.Body).Decode(&parsedResponse)
	if err != nil {
		return 0, fmt.Errorf("unable to parse response: %w", err)
	}

	return parsedResponse.Quota, nil
}

// quotaCheckRequest is JSON request to license server to check quota for a given license and action.
type quotaCheckRequest struct {
	Action   Action `json:"action"`
	Provider string `json:"provider"`
	License  string `json:"license"`
}

// quotaCheckResponse is JSON response by license server.
type quotaCheckResponse struct {
	Quota int `json:"quota"`
}

func licenseURL() *url.URL {
	return &url.URL{
		Scheme: "https",
		Host:   apiHost,
		Path:   licensePath,
	}
}