// internal/templating/engine.go
package templating

import (
	"bytes"
	"fmt"
	"os"
	"path/filepath"
	"text/template"

	"gopkg.in/yaml.v3"
)

// LoadTemplate 从文件加载 YAML 模板
func LoadTemplate(path string) (*Template, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("无法读取模板文件 %s: %w", path, err)
	}
	var tmpl Template
	if err := yaml.Unmarshal(data, &tmpl); err != nil {
		return nil, fmt.Errorf("YAML 解析失败: %w", err)
	}
	return &tmpl, nil
}

// Render 渲染模板为具体操作
func (t *Template) Render(ctx Context) (map[string][]RenderedStep, error) {
	result := make(map[string][]RenderedStep)

	for stageName, steps := range t.Stages {
		var renderedSteps []RenderedStep
		for _, step := range steps {
			// 处理 condition
			if step.Condition != "" {
				condTmpl, err := template.New("condition").Parse(step.Condition)
				if err != nil {
					return nil, fmt.Errorf("条件模板语法错误: %w", err)
				}
				var buf bytes.Buffer
				if err := condTmpl.Execute(&buf, ctx); err != nil {
					return nil, fmt.Errorf("执行条件模板失败: %w", err)
				}
				if buf.String() == "" {
					continue // 条件不满足，跳过
				}
			}

			// 渲染 content
			contentTmpl, err := template.New("content").Parse(step.Content)
			if err != nil {
				return nil, fmt.Errorf("内容模板语法错误: %w", err)
			}
			var buf bytes.Buffer
			if err := contentTmpl.Execute(&buf, ctx); err != nil {
				return nil, fmt.Errorf("执行内容模板失败: %w", err)
			}

			renderedSteps = append(renderedSteps, RenderedStep{
				Type:    step.Type,
				Path:    step.Path,
				Content: buf.String(),
			})
		}
		result[stageName] = renderedSteps
	}
	return result, nil
}

// RenderedStep 是渲染后的步骤
type RenderedStep struct {
	Type    string
	Path    string
	Content string
}

// WriteFiles 将 file 类型步骤写入磁盘
func WriteFiles(steps []RenderedStep, rootDir string) error {
	for _, s := range steps {
		if s.Type != "file" {
			continue
		}
		fullPath := s.Path
		if !filepath.IsAbs(s.Path) {
			fullPath = filepath.Join(rootDir, s.Path)
		}
		if err := os.MkdirAll(filepath.Dir(fullPath), 0755); err != nil {
			return err
		}
		if err := os.WriteFile(fullPath, []byte(s.Content), 0644); err != nil {
			return fmt.Errorf("写入文件 %s 失败: %w", fullPath, err)
		}
	}
	return nil
}

// PrintScripts 打印 script 内容（安全起见，先不自动执行）
func PrintScripts(steps []RenderedStep) {
	for _, s := range steps {
		if s.Type == "script" {
			fmt.Printf("# --- 脚本开始 ---\n%s\n# --- 脚本结束 ---\n", s.Content)
		}
	}
}
