package services

import (
	"encoding/json"
	"fmt"

	"gitea.hostxtra.co.uk/mrhid6/vantage/server/internal/models"
)

const StepDocKind = "vantage.step/v1"

type StepDoc struct {
	Kind            string              `json:"kind"`
	Name            string              `json:"name"`
	Description     string              `json:"description"`
	Interpreter     string              `json:"interpreter"`
	Script          string              `json:"script"`
	DeclaredOutputs []string            `json:"declared_outputs"`
	DeclaredInputs  []models.InputParam `json:"declared_inputs"`
	SecretRefs      []string            `json:"secret_refs"`
}

func ExportStepDoc(s models.WorkflowStep) StepDoc {
	return StepDoc{
		Kind:            StepDocKind,
		Name:            s.Name,
		Description:     s.Description,
		Interpreter:     s.Interpreter,
		Script:          s.Script,
		DeclaredOutputs: s.DeclaredOutputs,
		DeclaredInputs:  s.DeclaredInputs,
		SecretRefs:      s.SecretRefs,
	}
}

func ParseStepDoc(b []byte) (models.WorkflowStep, error) {
	var d StepDoc
	if err := json.Unmarshal(b, &d); err != nil {
		return models.WorkflowStep{}, fmt.Errorf("invalid step JSON: %w", err)
	}
	if d.Kind != StepDocKind {
		return models.WorkflowStep{}, fmt.Errorf("unsupported kind %q (want %q)", d.Kind, StepDocKind)
	}
	if d.Name == "" || d.Interpreter == "" {
		return models.WorkflowStep{}, fmt.Errorf("step name and interpreter are required")
	}
	if d.SecretRefs == nil {
		d.SecretRefs = []string{}
	}
	if d.DeclaredInputs == nil {
		d.DeclaredInputs = []models.InputParam{}
	}
	return models.WorkflowStep{
		Name:            d.Name,
		Description:     d.Description,
		Interpreter:     d.Interpreter,
		Script:          d.Script,
		DeclaredOutputs: DeriveOutputs(d.Script),
		DeclaredInputs:  d.DeclaredInputs,
		SecretRefs:      d.SecretRefs,
	}, nil
}

func ImportStepToLibrary(instanceID string, b []byte) (*models.WorkflowStep, error) {
	s, err := ParseStepDoc(b)
	if err != nil {
		return nil, err
	}
	return CreateStep(instanceID, s)
}

func ExportStep(instanceID, stepID string) ([]byte, error) {
	ctx, cancel := wfCtx()
	defer cancel()
	s, err := getStep(ctx, instanceID, stepID)
	if err != nil {
		return nil, err
	}
	return json.MarshalIndent(ExportStepDoc(*s), "", "  ")
}
