package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"strings"

	"sub2api-cn-relay-manager/internal/overlay"
	"sub2api-cn-relay-manager/internal/pack"
)

type applyHostOverlayFunc func(context.Context, applyHostOverlayCLIRequest) (overlay.ApplyResult, error)

type applyHostOverlayCLIRequest struct {
	PackDir     string
	ProviderID  string
	HostVersion string
	SourceDir   string
	OutputDir   string
	TargetHost  string
	OverlayID   string
}

func parseApplyHostOverlayCLIArgs(args []string) (applyHostOverlayCLIRequest, error) {
	fs := flag.NewFlagSet("apply-host-overlay", flag.ContinueOnError)
	fs.SetOutput(io.Discard)

	var req applyHostOverlayCLIRequest
	fs.StringVar(&req.PackDir, "pack-dir", "", "")
	fs.StringVar(&req.ProviderID, "provider-id", "", "")
	fs.StringVar(&req.HostVersion, "host-version", "", "")
	fs.StringVar(&req.SourceDir, "source-dir", "", "")
	fs.StringVar(&req.OutputDir, "output-dir", "", "")
	fs.StringVar(&req.TargetHost, "target-host", "", "")
	fs.StringVar(&req.OverlayID, "overlay-id", "", "")
	if err := fs.Parse(args); err != nil {
		return applyHostOverlayCLIRequest{}, err
	}

	switch {
	case strings.TrimSpace(req.PackDir) == "":
		return applyHostOverlayCLIRequest{}, fmt.Errorf("--pack-dir is required")
	case strings.TrimSpace(req.ProviderID) == "":
		return applyHostOverlayCLIRequest{}, fmt.Errorf("--provider-id is required")
	case strings.TrimSpace(req.HostVersion) == "":
		return applyHostOverlayCLIRequest{}, fmt.Errorf("--host-version is required")
	case strings.TrimSpace(req.SourceDir) == "":
		return applyHostOverlayCLIRequest{}, fmt.Errorf("--source-dir is required")
	}
	return req, nil
}

func runApplyHostOverlay(ctx context.Context, req applyHostOverlayCLIRequest) (overlay.ApplyResult, error) {
	loadedPack, err := pack.LoadDir(req.PackDir)
	if err != nil {
		return overlay.ApplyResult{}, err
	}
	providerManifest, err := findProvider(loadedPack, req.ProviderID)
	if err != nil {
		return overlay.ApplyResult{}, err
	}

	targetHost := strings.TrimSpace(req.TargetHost)
	if targetHost == "" {
		targetHost = loadedPack.Manifest.TargetHost
	}
	resolvedOverlays, err := pack.ResolveApplicableHostOverlays(providerManifest, targetHost, req.HostVersion)
	if err != nil {
		return overlay.ApplyResult{}, err
	}
	if len(resolvedOverlays) == 0 {
		return overlay.ApplyResult{}, fmt.Errorf("no host overlays matched provider %q for host %q version %q", req.ProviderID, targetHost, req.HostVersion)
	}
	filteredOverlays, err := overlay.FilterOverlays(resolvedOverlays, req.OverlayID)
	if err != nil {
		return overlay.ApplyResult{}, err
	}

	return overlay.Apply(ctx, overlay.ApplyRequest{
		PackDir:   loadedPack.Dir,
		SourceDir: req.SourceDir,
		OutputDir: req.OutputDir,
		Overlays:  filteredOverlays,
	})
}
