package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/osbuild/image-builder-cli/pkg/progress"
	"github.com/osbuild/images/pkg/imagefilter"
)

type enhancedBuildOptions struct {
	OutputDir      string
	StoreDir       string
	OutputBasename string
	Formats        []string
	Blueprint      string
	WriteManifest  bool
	WriteBuildlog  bool
	ValidateOnly   bool
}

func enhancedBuildImage(pbar progress.ProgressBar, res *imagefilter.Result, osbuildManifest []byte, opts *enhancedBuildOptions) ([]string, error) {
	if opts == nil {
		opts = &enhancedBuildOptions{}
	}

	var outputs []string
	basename := basenameFor(res, opts.OutputBasename)

	// Handle blueprint if provided
	if opts.Blueprint != "" {
		if err := validateBlueprint(opts.Blueprint); err != nil {
			return nil, fmt.Errorf("blueprint validation failed: %w", err)
		}
		if opts.ValidateOnly {
			return []string{"blueprint validation passed"}, nil
		}
	}

	// Build for each requested format
	formats := opts.Formats
	if len(formats) == 0 {
		formats = []string{res.ImgType.Name()}
	}

	for _, format := range formats {
		output, err := buildSingleFormat(pbar, res, osbuildManifest, basename, format, opts)
		if err != nil {
			return outputs, fmt.Errorf("failed to build %s format: %w", format, err)
		}
		outputs = append(outputs, output)
	}

	return outputs, nil
}

func buildSingleFormat(pbar progress.ProgressBar, res *imagefilter.Result, osbuildManifest []byte, basename, format string, opts *enhancedBuildOptions) (string, error) {
	// Create output directory
	if err := os.MkdirAll(opts.OutputDir, 0755); err != nil {
		return "", fmt.Errorf("cannot create output directory: %w", err)
	}

	// Write manifest if requested
	if opts.WriteManifest {
		manifestPath := filepath.Join(opts.OutputDir, fmt.Sprintf("%s-%s.osbuild-manifest.json", basename, format))
		if err := os.WriteFile(manifestPath, osbuildManifest, 0644); err != nil {
			return "", fmt.Errorf("cannot write manifest: %w", err)
		}
	}

	// Configure osbuild options
	osbuildOpts := &progress.OSBuildOptions{
		StoreDir:  opts.StoreDir,
		OutputDir: opts.OutputDir,
	}

	// Handle build log
	if opts.WriteBuildlog {
		logPath := filepath.Join(opts.OutputDir, fmt.Sprintf("%s-%s.buildlog", basename, format))
		f, err := os.Create(logPath)
		if err != nil {
			return "", fmt.Errorf("cannot create buildlog: %w", err)
		}
		defer f.Close()
		osbuildOpts.BuildLog = f
	}

	// Run osbuild
	if err := progress.RunOSBuild(pbar, osbuildManifest, res.ImgType.Exports(), osbuildOpts); err != nil {
		return "", err
	}

	// Rename output file
	pipelineDir := filepath.Join(opts.OutputDir, res.ImgType.Exports()[0])
	srcName := filepath.Join(pipelineDir, res.ImgType.Filename())
	imgExt := strings.SplitN(res.ImgType.Filename(), ".", 2)[1]
	dstName := filepath.Join(opts.OutputDir, fmt.Sprintf("%s-%s.%s", basename, format, imgExt))
	
	if err := os.Rename(srcName, dstName); err != nil {
		return "", fmt.Errorf("cannot rename artifact to final name: %w", err)
	}

	// Clean up pipeline directory
	_ = os.Remove(pipelineDir)

	return dstName, nil
}

func validateBlueprint(blueprintPath string) error {
	// Read and parse blueprint
	data, err := os.ReadFile(blueprintPath)
	if err != nil {
		return fmt.Errorf("cannot read blueprint: %w", err)
	}

	// Basic validation - check if it's valid YAML/JSON
	if !strings.Contains(string(data), "packages:") && !strings.Contains(string(data), "users:") {
		return fmt.Errorf("blueprint appears to be invalid - missing required sections")
	}

	return nil
}

func getSupportedFormats() []string {
	return []string{
		"qcow2", "raw", "vmdk", "iso", "tar", "container",
	}
}
