package doctor

import (
	"os"
	"path/filepath"

	"github.com/tidbcloud/AgentTeam/desktop/internal/profile"
)

// CheckStatus represents the result of a single diagnostic check.
type CheckStatus string

const (
	StatusPass CheckStatus = "PASS"
	StatusWarn CheckStatus = "WARN"
	StatusFail CheckStatus = "FAIL"
)

// CheckResult holds the outcome of a single diagnostic check.
type CheckResult struct {
	Name   string      `json:"name"`
	Status CheckStatus `json:"status"`
	Detail string      `json:"detail"`
}

// DoctorResponse is the JSON response for the /doctor API.
type DoctorResponse struct {
	Results []CheckResult `json:"results"`
}

// DaemonChecker is an optional function that checks daemon status.
// This avoids an import cycle with the daemon package.
type DaemonChecker func() CheckResult

// RunChecks executes all diagnostic checks and returns their results.
// If daemonChecker is nil, the daemon status check is skipped.
// Runtime checks are excluded — they are managed in the Settings page.
func RunChecks(daemonChecker DaemonChecker) []CheckResult {
	results := make([]CheckResult, 0)

	results = append(results, checkConfigDir())
	results = append(results, checkConfigFile())
	results = append(results, checkConfigWritable())
	results = append(results, checkConfigValid())

	if daemonChecker != nil {
		results = append(results, daemonChecker())
	}

	return results
}

func checkConfigDir() CheckResult {
	dir := profile.ConfigDir()
	info, err := os.Stat(dir)
	if err != nil {
		if os.IsNotExist(err) {
			return CheckResult{"Config directory exists", StatusFail, "not found, run 'agentteam onboard' first"}
		}
		return CheckResult{"Config directory exists", StatusFail, err.Error()}
	}
	if !info.IsDir() {
		return CheckResult{"Config directory exists", StatusFail, "path exists but is not a directory"}
	}
	return CheckResult{"Config directory exists", StatusPass, dir}
}

func checkConfigFile() CheckResult {
	path := profile.Path()
	info, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return CheckResult{"Config file exists", StatusFail, "not found, run 'agentteam onboard' first"}
		}
		return CheckResult{"Config file exists", StatusFail, err.Error()}
	}
	if info.IsDir() {
		return CheckResult{"Config file exists", StatusFail, "path is a directory"}
	}
	return CheckResult{"Config file exists", StatusPass, path}
}

func checkConfigWritable() CheckResult {
	dir := profile.ConfigDir()
	tmpFile := filepath.Join(dir, ".agentteam_doctor_write_test")
	if err := os.WriteFile(tmpFile, []byte("test"), 0600); err != nil {
		return CheckResult{"Config directory writable", StatusFail, err.Error()}
	}
	_ = os.Remove(tmpFile)
	return CheckResult{"Config directory writable", StatusPass, dir}
}

func checkConfigValid() CheckResult {
	_, err := profile.Load(profile.Path())
	if err != nil {
		return CheckResult{"Config file valid", StatusFail, err.Error()}
	}
	return CheckResult{"Config file valid", StatusPass, "parsed successfully"}
}
