package tilt

import (
	"path/filepath"
	"strings"

	"github.com/tidbcloud/controlplane9/internal/cluster"
)

const (
	ReportsDirName        = "reports"
	ContextReportFileName = "context-report.json"
	StatusFileName        = "tilt-status.json"
	UpLogFileName         = "tilt-up.log"
	contextIndexFileName  = "context.json"
)

// Paths captures the persisted Tilt handoff/runtime paths for one session.
type Paths struct {
	TiltDir       string
	Tiltfile      string
	ContextIndex  string
	ReportsDir    string
	ContextReport string
	Status        string
	UpLog         string
}

// PathsForState resolves the persisted Tilt paths for one session, respecting
// any path overrides already recorded on the lifecycle state.
func PathsForState(stateDir string, state *cluster.State) Paths {
	tiltDir := cluster.TiltDir(stateDir)
	tiltfile := cluster.TiltfilePath(stateDir)
	contextDir := cluster.ContextDir(stateDir)
	if state != nil && state.Paths != nil {
		if value := strings.TrimSpace(state.Paths.TiltDir); value != "" {
			tiltDir = value
			tiltfile = filepath.Join(tiltDir, "Tiltfile")
		}
		if value := strings.TrimSpace(state.Paths.Tiltfile); value != "" {
			tiltfile = value
		}
		if value := strings.TrimSpace(state.Paths.ContextDir); value != "" {
			contextDir = value
		}
	}
	reportsDir := filepath.Join(tiltDir, ReportsDirName)
	return Paths{
		TiltDir:       tiltDir,
		Tiltfile:      tiltfile,
		ContextIndex:  filepath.Join(contextDir, contextIndexFileName),
		ReportsDir:    reportsDir,
		ContextReport: filepath.Join(reportsDir, ContextReportFileName),
		Status:        filepath.Join(reportsDir, StatusFileName),
		UpLog:         filepath.Join(reportsDir, UpLogFileName),
	}
}

func sessionRelativePath(stateDir, path string) string {
	if strings.TrimSpace(path) == "" {
		return ""
	}
	rel, err := filepath.Rel(stateDir, path)
	if err != nil {
		return filepath.ToSlash(path)
	}
	return filepath.ToSlash(rel)
}

func sessionAbsolutePath(stateDir, path string) string {
	if strings.TrimSpace(path) == "" {
		return ""
	}
	if filepath.IsAbs(path) {
		return filepath.Clean(path)
	}
	return filepath.Join(stateDir, filepath.FromSlash(path))
}

// SessionRelativePath converts one session-owned absolute path into a
// slash-normalized path relative to the session root.
func SessionRelativePath(stateDir, path string) string {
	return sessionRelativePath(stateDir, path)
}

// SessionAbsolutePath resolves one session-relative path back to an absolute
// path under the session root.
func SessionAbsolutePath(stateDir, path string) string {
	return sessionAbsolutePath(stateDir, path)
}
