// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

// Package osimage allows reading OS images represented as OCI artifacts, and
// contains the types for the OS image config.
package osimage

import (
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"

	"github.com/klauspost/compress/zstd"

	"source.monogon.dev/osbase/oci"
	"source.monogon.dev/osbase/structfs"
)

// Image represents an OS image.
type Image struct {
	// Config contains the parsed config.
	Config *Config
	// RawConfig contains the bytes of the config.
	RawConfig []byte

	image *oci.Image
}

// Read reads the config from an OCI image and returns an [Image].
func Read(image *oci.Image) (*Image, error) {
	manifest := image.Manifest
	if manifest.ArtifactType != ArtifactTypeOSImage {
		return nil, fmt.Errorf("unexpected manifest artifact type %q", manifest.ArtifactType)
	}
	if manifest.Config.MediaType != MediaTypeOSImageConfig {
		return nil, fmt.Errorf("unexpected config media type %q", manifest.Config.MediaType)
	}

	// Read the config.
	rawConfig, err := image.ReadBlobVerified(&manifest.Config)
	if err != nil {
		return nil, fmt.Errorf("failed to read config: %w", err)
	}
	config := &Config{}
	err = json.Unmarshal(rawConfig, &config)
	if err != nil {
		return nil, fmt.Errorf("failed to parse config: %w", err)
	}
	if config.FormatVersion != ConfigVersion {
		return nil, fmt.Errorf("unsupported config version %q", config.FormatVersion)
	}
	if len(config.Payloads) != len(manifest.Layers) {
		return nil, fmt.Errorf("number of layers %d does not match number of payloads %d", len(manifest.Layers), len(config.Payloads))
	}
	for i := range config.Payloads {
		payload := &config.Payloads[i]
		if payload.Size < 0 {
			return nil, fmt.Errorf("payload %q has negative size", payload.Name)
		}
		if payload.HashChunkSize <= 0 {
			return nil, fmt.Errorf("payload %q has invalid chunk size %d", payload.Name, payload.HashChunkSize)
		}
		if payload.HashChunkSize > 16*1024*1024 {
			return nil, fmt.Errorf("payload %q has too large chunk size %d", payload.Name, payload.HashChunkSize)
		}
		chunks := payload.Size / payload.HashChunkSize
		if chunks*payload.HashChunkSize < payload.Size {
			chunks++
		}
		if int64(len(payload.ChunkHashesSHA256)) != chunks {
			return nil, fmt.Errorf("payload %q has %d chunks but %d chunk hashes", payload.Name, chunks, len(payload.ChunkHashesSHA256))
		}
	}

	osImage := &Image{
		Config:    config,
		RawConfig: rawConfig,
		image:     image,
	}
	return osImage, nil
}

// Payload returns the contents of the payload of the given name.
// All data is verified against hashes in the config before it is returned.
func (i *Image) Payload(name string) (structfs.Blob, error) {
	for pi := range i.Config.Payloads {
		info := &i.Config.Payloads[pi]
		if info.Name == name {
			layer := &i.image.Manifest.Layers[pi]
			blob := &payloadBlob{
				raw:       i.image.StructfsBlob(layer),
				mediaType: layer.MediaType,
				info:      info,
			}
			return blob, nil
		}
	}
	return nil, fmt.Errorf("payload %q not found", name)
}

type payloadBlob struct {
	raw       structfs.Blob
	mediaType string
	info      *PayloadInfo
}

func (b *payloadBlob) Open() (io.ReadCloser, error) {
	blobReader, err := b.raw.Open()
	if err != nil {
		return nil, err
	}
	reader := &payloadReader{
		chunkHashes: b.info.ChunkHashesSHA256,
		blobReader:  blobReader,
		remaining:   b.info.Size,
		buf:         make([]byte, b.info.HashChunkSize),
	}
	switch b.mediaType {
	case MediaTypePayloadUncompressed:
		reader.uncompressed = blobReader
	case MediaTypePayloadZstd:
		reader.zstdDecoder, err = zstd.NewReader(blobReader)
		if err != nil {
			blobReader.Close()
			return nil, fmt.Errorf("failed to create zstd decoder: %w", err)
		}
		reader.uncompressed = reader.zstdDecoder
	default:
		blobReader.Close()
		return nil, fmt.Errorf("unsupported media type %q", b.mediaType)
	}
	return reader, nil
}

func (b *payloadBlob) Size() int64 {
	return b.info.Size
}

type payloadReader struct {
	chunkHashes  []string
	blobReader   io.ReadCloser
	zstdDecoder  *zstd.Decoder
	uncompressed io.Reader
	remaining    int64  // number of bytes remaining in uncompressed
	buf          []byte // buffer of chunk size
	available    []byte // bytes available for reading in the last read chunk
}

func (r *payloadReader) Read(p []byte) (n int, err error) {
	if len(r.available) != 0 {
		n = copy(p, r.available)
		r.available = r.available[n:]
		return
	}
	if r.remaining == 0 {
		err = io.EOF
		return
	}
	chunkLen := min(r.remaining, int64(len(r.buf)))
	chunk := r.buf[:chunkLen]
	_, err = io.ReadFull(r.uncompressed, chunk)
	if err != nil {
		if err == io.EOF {
			err = io.ErrUnexpectedEOF
		}
		r.remaining = 0
		return
	}
	chunkHashBytes := sha256.Sum256(chunk)
	chunkHash := base64.RawStdEncoding.EncodeToString(chunkHashBytes[:])
	if chunkHash != r.chunkHashes[0] {
		err = fmt.Errorf("payload failed verification against chunk hash, expected %q, got %q", r.chunkHashes[0], chunkHash)
		r.remaining = 0
		return
	}
	r.chunkHashes = r.chunkHashes[1:]
	r.remaining -= chunkLen
	n = copy(p, chunk)
	r.available = chunk[n:]
	return
}

func (r *payloadReader) Close() error {
	if r.zstdDecoder != nil {
		r.zstdDecoder.Close()
	}
	return r.blobReader.Close()
}
