package daemon

import (
	"context"
	"fmt"

	"github.com/moby/moby/api/types/container"
	"github.com/moby/moby/v2/daemon/internal/filters"
	"github.com/moby/moby/v2/daemon/server/backend"
	"github.com/moby/moby/v2/daemon/server/imagebackend"
	"github.com/pkg/errors"
	"golang.org/x/sync/errgroup"
)

// containerDiskUsage obtains information about container data disk usage
// and makes sure that only one calculation is performed at the same time.
func (daemon *Daemon) containerDiskUsage(ctx context.Context, verbose bool) (*backend.ContainerDiskUsage, error) {
	res, _, err := daemon.usageContainers.Do(ctx, verbose, func(ctx context.Context) (*backend.ContainerDiskUsage, error) {
		// Retrieve container list
		containers, err := daemon.Containers(ctx, &backend.ContainerListOptions{
			Size: true,
			All:  true,
		})
		if err != nil {
			return nil, fmt.Errorf("failed to retrieve container list: %v", err)
		}

		du := &backend.ContainerDiskUsage{
			ActiveCount: int64(len(containers)),
			TotalCount:  int64(len(containers)),
		}
		for i := range containers {
			du.TotalSize += containers[i].SizeRw
			switch containers[i].State {
			case container.StateRunning, container.StatePaused, container.StateRestarting:
				// active
			default:
				du.Reclaimable += containers[i].SizeRw
				du.ActiveCount--
			}

			// Remove image manifest descriptor from the result as it should not be included.
			// https://github.com/moby/moby/pull/49407#discussion_r1954396666
			containers[i].ImageManifestDescriptor = nil
		}

		if verbose {
			du.Items = containers
		}

		return du, nil
	})
	return res, err
}

// imageDiskUsage obtains information about image data disk usage from image service
// and makes sure that only one calculation is performed at the same time.
func (daemon *Daemon) imageDiskUsage(ctx context.Context, verbose bool) (*backend.ImageDiskUsage, error) {
	du, _, err := daemon.usageImages.Do(ctx, verbose, func(ctx context.Context) (*backend.ImageDiskUsage, error) {
		// Get all top images with extra attributes
		images, err := daemon.imageService.Images(ctx, imagebackend.ListOptions{
			Filters:    filters.NewArgs(),
			SharedSize: true,
		})
		if err != nil {
			return nil, errors.Wrap(err, "failed to retrieve image list")
		}

		totalSize, _, err := daemon.usageLayer.Do(ctx, struct{}{}, func(ctx context.Context) (int64, error) {
			return daemon.imageService.ImageDiskUsage(ctx)
		})
		if err != nil {
			return nil, errors.Wrap(err, "failed to calculate image disk usage")
		}

		du := &backend.ImageDiskUsage{
			TotalCount: int64(len(images)),
			TotalSize:  totalSize,
		}

		for _, img := range images {
			switch {
			case img.Containers < 0:
				// No container-count information available; skip (assume it's in use).
			case img.Containers > 0:
				du.ActiveCount++
			case img.Containers == 0 && img.Size != -1 && img.SharedSize != -1:
				reclaimable := img.Size - img.SharedSize
				du.Reclaimable += reclaimable
			}
		}

		if verbose {
			du.Items = images
		}

		return du, nil
	})

	return du, err
}

// localVolumesSize obtains information about volume disk usage from volumes service
// and makes sure that only one size calculation is performed at the same time.
func (daemon *Daemon) localVolumesSize(ctx context.Context, verbose bool) (*backend.VolumeDiskUsage, error) {
	volumes, _, err := daemon.usageVolumes.Do(ctx, verbose, func(ctx context.Context) (*backend.VolumeDiskUsage, error) {
		volumes, err := daemon.volumes.LocalVolumesSize(ctx)
		if err != nil {
			return nil, err
		}

		du := &backend.VolumeDiskUsage{
			ActiveCount: int64(len(volumes)),
			TotalCount:  int64(len(volumes)),
		}
		for _, v := range volumes {
			if v.UsageData.Size != -1 {
				du.TotalSize += v.UsageData.Size
				if v.UsageData.RefCount == 0 {
					du.Reclaimable += v.UsageData.Size
					du.ActiveCount--
				}
			}
		}

		if verbose {
			du.Items = volumes
		}

		return du, nil
	})
	return volumes, err
}

// SystemDiskUsage returns information about the daemon data disk usage.
// Callers must not mutate contents of the returned fields.
func (daemon *Daemon) SystemDiskUsage(ctx context.Context, opts backend.DiskUsageOptions) (*backend.DiskUsage, error) {
	eg, ctx := errgroup.WithContext(ctx)

	du := &backend.DiskUsage{}
	if opts.Containers {
		eg.Go(func() (err error) {
			du.Containers, err = daemon.containerDiskUsage(ctx, opts.Verbose)
			return err
		})
	}

	if opts.Images {
		eg.Go(func() (err error) {
			du.Images, err = daemon.imageDiskUsage(ctx, opts.Verbose)
			return err
		})
	}

	if opts.Volumes {
		eg.Go(func() (err error) {
			du.Volumes, err = daemon.localVolumesSize(ctx, opts.Verbose)
			return err
		})
	}

	if err := eg.Wait(); err != nil {
		return nil, err
	}

	return du, nil
}
