package plan

import (
	"fmt"
	"path/filepath"

	"github.com/tidbcloud/observability/vm-migration/internal/jsonio"
	"github.com/tidbcloud/observability/vm-migration/internal/schema"
	"github.com/tidbcloud/observability/vm-migration/internal/tenants"
)

// CompileOptions carries the inputs to a compile run.
type CompileOptions struct {
	Plan    string // path to json template
	Tenants string // flat tenant list written by tenants merge
	Output  string // optional; defaults to <plan-stem>-compile.json
}

// CompileResult captures the file paths produced by a successful compile.
type CompileResult struct {
	CompilePath string // <plan-stem>-compile.json
}

// Compile validates the source plan and tenant inventory, then writes a
// compact compiled plan.
//
// Tenant-specific command expansion remains prepare's job.
func Compile(opts CompileOptions) (*CompileResult, error) {
	tenantIDs, err := tenants.ReadFile(opts.Tenants)
	if err != nil {
		return nil, err
	}
	if len(tenantIDs) == 0 {
		return nil, fmt.Errorf("no tenants in %s", opts.Tenants)
	}

	cfg, stages, err := Load(opts.Plan)
	if err != nil {
		return nil, err
	}

	normalizedTenants, _, err := NormalizeTenantIDs(tenantIDs)
	if err != nil {
		return nil, err
	}
	cfg.Tenants = normalizedTenants
	compilePath, err := WriteCompiled(opts.Plan, opts.Output, cfg, stages)
	if err != nil {
		return nil, err
	}
	return &CompileResult{CompilePath: compilePath}, nil
}

// WritePerTenantFiles materializes the per-tenant inventory files of a
// compiled migration loop: one tenants-<stem>.json per tenant, holding that
// tenant's id.
func WritePerTenantFiles(dir string, loopPlan *schema.MigrationLoopPlan) error {
	for _, t := range loopPlan.Tenants {
		path := filepath.Join(dir, t.TenantsFile)
		if err := jsonio.WriteFile(path, []string{t.Name}); err != nil {
			return fmt.Errorf("write %s: %w", path, err)
		}
	}
	return nil
}
