package ops

import (
	"encoding/json"
	"errors"
	"path/filepath"
	"strings"

	"ops-assistant/internal/core/runbook"
	"ops-assistant/models"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

func decodeInputJSON(raw string, out *map[string]string) error {
	if strings.TrimSpace(raw) == "" {
		return nil
	}
	return json.Unmarshal([]byte(raw), out)
}

func RetryJobWithDB(db *gorm.DB, baseDir string, jobID uint) (uint, error) {
	if db == nil {
		return 0, errors.New("db is nil")
	}
	var old models.OpsJob
	if err := db.First(&old, jobID).Error; err != nil {
		return 0, err
	}
	if strings.TrimSpace(old.Status) != "failed" {
		return 0, errors.New("only failed jobs can retry")
	}

	inputs := map[string]string{}
	if strings.TrimSpace(old.InputJSON) != "" {
		_ = decodeInputJSON(old.InputJSON, &inputs)
	}

	meta := runbook.NewMeta()
	meta.Target = old.Target
	meta.RiskLevel = old.RiskLevel
	meta.RequestID = old.RequestID + "-retry"
	meta.ConfirmHash = old.ConfirmHash

	exec := runbook.NewExecutor(db, filepath.Join(baseDir, "runbooks"))
	newID, _, err := exec.RunWithInputsAndMeta(old.Command, old.Runbook, old.Operator, inputs, meta)
	if err != nil {
		return newID, err
	}
	return newID, nil
}

func RetryJob(dbPath, baseDir string, jobID uint) (uint, error) {
	db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
	if err != nil {
		return 0, err
	}
	return RetryJobWithDB(db, baseDir, jobID)
}
