/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/

package extract

import (
	"encoding/json"
	"fmt"
	"io"
	"regexp"
)

var digestRegexp = regexp.MustCompile(`^sha256:[0-9a-f]{64}$`)

const (
	supportedSchemaVersion = 2
	supportedMediaType     = "application/vnd.oci.image.index.v1+json"
)

// Digest extracts the digest from an OCI index.
func Digest(index io.Reader) (string, error) {
	var oci ociIndex
	if err := json.NewDecoder(index).Decode(&oci); err != nil {
		return "", fmt.Errorf("decoding oci index: %w", err)
	}
	if oci.SchemaVersion != supportedSchemaVersion {
		return "", fmt.Errorf("unsupported schema version %d", oci.SchemaVersion)
	}
	if oci.MediaType != supportedMediaType {
		return "", fmt.Errorf("unsupported media type %q", oci.MediaType)
	}
	if len(oci.Manifests) != 1 {
		return "", fmt.Errorf("expected 1 manifest, got %d", len(oci.Manifests))
	}
	digest := oci.Manifests[0].Digest
	if matched := digestRegexp.MatchString(digest); !matched {
		return "", fmt.Errorf("malformed digest %q", digest)
	}

	return digest, nil
}

type ociIndex struct {
	SchemaVersion int    `json:"schemaVersion"`
	MediaType     string `json:"mediaType"`
	Manifests     []struct {
		MediaType string `json:"mediaType"`
		Digest    string `json:"digest"`
	} `json:"manifests"`
}