package docker

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"github.com/moby/moby/client"
)

// SiteVolumeName returns the deterministic volume name for a static site.
func SiteVolumeName(siteName string) string {
	return fmt.Sprintf("tinyforge-site-%s-data", siteName)
}

// EnsureSiteVolume creates a named volume for a static site if it doesn't already exist.
// Returns the volume name.
func (c *Client) EnsureSiteVolume(ctx context.Context, siteName string) (string, error) {
	name := SiteVolumeName(siteName)

	// Check if volume already exists.
	_, err := c.api.VolumeInspect(ctx, name, client.VolumeInspectOptions{})
	if err == nil {
		return name, nil
	}

	// Create the volume.
	_, err = c.api.VolumeCreate(ctx, client.VolumeCreateOptions{
		Name: name,
		Labels: map[string]string{
			"tinyforge.static-site": "true",
			"tinyforge.site-name":   siteName,
		},
	})
	if err != nil {
		return "", fmt.Errorf("create volume %s: %w", name, err)
	}

	return name, nil
}

// RemoveSiteVolume removes the named volume for a static site.
func (c *Client) RemoveSiteVolume(ctx context.Context, siteName string) error {
	name := SiteVolumeName(siteName)
	_, err := c.api.VolumeRemove(ctx, name, client.VolumeRemoveOptions{Force: true})
	if err != nil {
		return fmt.Errorf("remove volume %s: %w", name, err)
	}
	return nil
}

// StorageUsage holds the disk usage info for a site volume.
type StorageUsage struct {
	UsedBytes int64 `json:"used_bytes"`
}

// InspectSiteStorageUsage execs `du -sb /app/data` inside the container to get usage.
// Returns 0 if the container is not running or the path doesn't exist.
func (c *Client) InspectSiteStorageUsage(ctx context.Context, containerID string) (StorageUsage, error) {
	if containerID == "" {
		return StorageUsage{}, nil
	}

	output, err := c.ExecInContainer(ctx, containerID, []string{"du", "-sb", "/app/data"})
	if err != nil {
		// Container not running or path doesn't exist — return zero.
		return StorageUsage{}, nil
	}

	// du output: "12345\t/app/data\n"
	parts := strings.Fields(strings.TrimSpace(output))
	if len(parts) == 0 {
		return StorageUsage{}, nil
	}

	bytes, err := strconv.ParseInt(parts[0], 10, 64)
	if err != nil {
		return StorageUsage{}, nil
	}

	return StorageUsage{UsedBytes: bytes}, nil
}
