// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package packages

import (
	"context"
	"fmt"
	"math/rand"
	"net/url"

	"go.fuchsia.dev/fuchsia/src/sys/pkg/bin/pm/build"
	"go.fuchsia.dev/fuchsia/src/testing/host-target-testing/util"
	"go.fuchsia.dev/fuchsia/tools/lib/logger"
)

type UpdateImages struct {
	repo       *Repository
	images     util.ImagesManifest
	zbiPackage Package

	// The zbiUrl and vbmetaUrl only differ on the fragment.
	zbiUrl    *url.URL
	vbmetaUrl *url.URL
}

func newUpdateImages(
	ctx context.Context,
	repo *Repository,
	images util.ImagesManifest,
) (*UpdateImages, error) {
	// Create a new zbi+vbmeta package that points at the system image package.
	zbiUrl, zbiMerkle, err := images.GetPartition("fuchsia", "zbi")
	if err != nil {
		return nil, fmt.Errorf("failed to read zbi from images manifest: %w", err)
	}

	if zbiUrl.Fragment == "" {
		return nil, fmt.Errorf("url must have fragment for zbi: %q", zbiUrl)
	}

	vbmetaUrl, _, err := images.GetPartition("fuchsia", "vbmeta")
	if err != nil {
		return nil, fmt.Errorf("failed to read vbmeta from images manifest: %w", err)
	}

	if vbmetaUrl.Fragment == "" {
		return nil, fmt.Errorf("url must have fragment for vbmeta: %q", vbmetaUrl)
	}

	// TODO(http://b/309019440): While it's possible to produce an `images.json`
	// file that has the `zbi` and `vbmeta` files in separate packages, we only
	// support these files being in the same package (which happens to be what
	// the fuchsia build produces). That's because when we use `avbtool.py` to
	// generate the new `vbmeta`, it'll open the `zbi` with `r+`. It's a lot
	// easier for us if both of these files are in the same package so we don't
	// need to copy files around or iteratively generate packages.
	//
	// Because of that, require that these urls are the same, other than the
	// fragment.
	zbiU := *zbiUrl
	vbmetaU := *vbmetaUrl
	zbiU.Fragment = ""
	vbmetaU.Fragment = ""

	if zbiU.String() != vbmetaU.String() {
		return nil, fmt.Errorf(
			"zbi and vbmeta package URLs should only differ on fragment: %s != %s",
			zbiUrl,
			vbmetaUrl,
		)
	}

	zbiPath := zbiUrl.Path[1:]
	zbiPackage, err := newPackage(ctx, repo, zbiPath, zbiMerkle)
	if err != nil {
		return nil, err
	}

	return &UpdateImages{
		repo:       repo,
		images:     images,
		zbiUrl:     zbiUrl,
		vbmetaUrl:  vbmetaUrl,
		zbiPackage: zbiPackage,
	}, nil
}

func (u *UpdateImages) replaceZbiPackage(
	ctx context.Context,
	dstZbi Package,
) (*UpdateImages, error) {
	images := u.images.Clone()

	// Update the zbi partition entry.
	dstZbiUrlString := fmt.Sprintf(
		"fuchsia-pkg://%s/%s?hash=%s#%s",
		u.zbiUrl.Host,
		dstZbi.Path(),
		dstZbi.Merkle(),
		u.zbiUrl.Fragment,
	)
	dstZbiUrl, err := url.Parse(dstZbiUrlString)
	if err != nil {
		return nil, fmt.Errorf("failed to parse url %s: %w", dstZbiUrlString, err)
	}
	logger.Infof(ctx, "updating update image zbi package url to %s", dstZbiUrl)

	zbiBlobPath, err := dstZbi.FilePath(ctx, u.zbiUrl.Fragment)
	if err != nil {
		return nil, fmt.Errorf("failed to find zbi blob path for %s: %w", u.zbiUrl.Fragment, err)
	}

	if err := images.SetPartition("fuchsia", "zbi", dstZbiUrl.String(), zbiBlobPath); err != nil {
		return nil, fmt.Errorf("failed to set zbi partition: %w", err)
	}

	dstVbmetaUrlString := fmt.Sprintf(
		"fuchsia-pkg://%s/%s?hash=%s#%s",
		u.vbmetaUrl.Host,
		dstZbi.Path(),
		dstZbi.Merkle(),
		u.vbmetaUrl.Fragment,
	)
	dstVbmetaUrl, err := url.Parse(dstVbmetaUrlString)
	if err != nil {
		return nil, fmt.Errorf("failed to parse url %s: %w", dstVbmetaUrlString, err)
	}
	logger.Infof(ctx, "updating update image vbmeta package url to %s", dstVbmetaUrl)

	vbmetaBlobPath, err := dstZbi.FilePath(ctx, u.vbmetaUrl.Fragment)
	if err != nil {
		return nil, fmt.Errorf("failed to find zbi blob path for %s: %w", u.vbmetaUrl.Fragment, err)
	}

	if err := images.SetPartition("fuchsia", "vbmeta", dstVbmetaUrl.String(), vbmetaBlobPath); err != nil {
		return nil, fmt.Errorf("failed to set vbmeta partition: %w", err)
	}

	return newUpdateImages(ctx, u.repo, images)
}

func (u *UpdateImages) zbiPath() string {
	return u.zbiUrl.Fragment
}

func (u *UpdateImages) vbmetaPath() string {
	return u.vbmetaUrl.Fragment
}

func (u *UpdateImages) Rehost(newHostname string) error {
	return u.images.Rehost(newHostname)
}

// Create a new zbi+vbmeta package
func (u *UpdateImages) EditZbiAndVbmetaPackage(
	ctx context.Context,
	editFunc func(p Package, zbiName string, vbmetaName string) (Package, error),
) (*UpdateImages, error) {
	dstZbi, err := editFunc(u.zbiPackage, u.zbiUrl.Fragment, u.vbmetaUrl.Fragment)
	if err != nil {
		return nil, err
	}

	return u.replaceZbiPackage(ctx, dstZbi)

}

func (u *UpdateImages) EditZbiAndVbmetaContents(
	ctx context.Context,
	dstPath string,
	editFunc func(tempDir string, zbiName string, vbmetaName string) error,
) (*UpdateImages, error) {
	return u.EditZbiAndVbmetaPackage(
		ctx,
		func(p Package, zbiName string, vbmetaName string) (Package, error) {
			return p.EditContents(ctx, dstPath, func(tempDir string) error {
				return editFunc(tempDir, zbiName, vbmetaName)
			})
		},
	)
}

func (u *UpdateImages) UpdateImagesAlignedBlobSize(ctx context.Context) (uint64, error) {
	blobs, err := u.UpdateImagesBlobs(ctx)
	if err != nil {
		return 0, err
	}

	return u.repo.sumAlignedBlobSizes(ctx, blobs)
}

func (u *UpdateImages) UpdateImagesBlobs(ctx context.Context) (map[build.MerkleRoot]struct{}, error) {
	return u.updateImagesBlobs(ctx, false)
}

func (u *UpdateImages) updateImagesBlobs(
	ctx context.Context,
	ignoreZbi bool,
) (map[build.MerkleRoot]struct{}, error) {
	visitedPackages := make(map[build.MerkleRoot]struct{})
	blobs := make(map[build.MerkleRoot]struct{})

	for _, partition := range u.images.Contents.Partitions {
		url, merkle, err := util.ParsePackageUrl(partition.Url)
		if err != nil {
			return nil, err
		}

		if ignoreZbi && u.zbiPackage.Merkle() == merkle {
			continue
		}

		pkg, err := newPackage(ctx, u.repo, url.Path[1:], merkle)
		if err != nil {
			return nil, err
		}

		if err := pkg.transitiveBlobs(ctx, visitedPackages, blobs); err != nil {
			return nil, err
		}
	}

	for _, firmware := range u.images.Contents.Firmware {
		url, merkle, err := util.ParsePackageUrl(firmware.Url)
		if err != nil {
			return nil, err
		}

		pkg, err := newPackage(ctx, u.repo, url.Path[1:], merkle)
		if err != nil {
			return nil, err
		}

		if err := pkg.transitiveBlobs(ctx, visitedPackages, blobs); err != nil {
			return nil, err
		}
	}

	return blobs, nil
}

func (u *UpdateImages) AddRandomFilesWithUpperBound(
	ctx context.Context,
	rand *rand.Rand,
	dstUpdateImagesPath string,
	maxSize uint64,
) (*UpdateImages, error) {
	additionalBlobs, err := u.updateImagesBlobs(ctx, true)
	if err != nil {
		return nil, err
	}

	return u.EditZbiAndVbmetaPackage(
		ctx,
		func(p Package, zbiName string, vbmetaName string) (Package, error) {
			return p.addRandomFilesWithUpperBound(
				ctx,
				rand,
				dstUpdateImagesPath,
				maxSize,
				additionalBlobs,
			)
		},
	)
}
