package agent

import (
	"bufio"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/tidbcloud/AgentTeam/desktop/internal/agent/runtimeconfig"
)

var (
	errClaudeConversationNotFound = errors.New("claude transcript not found")
)

// CanResumeSession is reserved for explicit runtime recovery boundaries that
// must validate a native transcript (for example Claude resume-at rewind). It
// must not be used as a preflight gate for ordinary provider-session resume.
func CanResumeSession(runtime string, sessionID string) (bool, error) {
	trimmedRuntime := strings.TrimSpace(runtime)
	trimmedSessionID := strings.TrimSpace(sessionID)
	if trimmedSessionID == "" {
		return false, nil
	}

	switch trimmedRuntime {
	case string(runtimeconfig.TypeClaudeCode):
		_, err := findClaudeConversationFile(trimmedSessionID)
		if errors.Is(err, errClaudeConversationNotFound) {
			return false, nil
		}
		return err == nil, err
	default:
		return true, nil
	}
}

// ---------------------------------------------------------------------------
// Claude session probing
// ---------------------------------------------------------------------------

func findClaudeConversationFile(sessionID string) (string, error) {
	files, err := claudeConversationFiles(sessionID)
	if err != nil {
		return "", err
	}
	if len(files) == 0 {
		return "", errClaudeConversationNotFound
	}
	return files[0], nil
}

func claudeTranscriptContainsUUID(sessionID string, wantUUID string) (bool, error) {
	wantUUID = strings.TrimSpace(wantUUID)
	if wantUUID == "" {
		return false, nil
	}
	path, err := findClaudeConversationFile(sessionID)
	if err != nil {
		return false, err
	}
	file, err := os.Open(path)
	if err != nil {
		return false, fmt.Errorf("open claude transcript: %w", err)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	scanner.Buffer(make([]byte, 0, 64*1024), 16*1024*1024)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" {
			continue
		}
		var entry struct {
			UUID string `json:"uuid"`
		}
		if err := json.Unmarshal([]byte(line), &entry); err != nil {
			continue
		}
		if strings.TrimSpace(entry.UUID) == wantUUID {
			return true, nil
		}
	}
	if err := scanner.Err(); err != nil {
		return false, fmt.Errorf("read claude transcript: %w", err)
	}
	return false, nil
}

func claudeConversationFiles(sessionID string) ([]string, error) {
	sessionID = strings.TrimSpace(sessionID)
	if sessionID == "" {
		return nil, errClaudeConversationNotFound
	}

	pattern := filepath.Join(claudeProjectsDir(), "*", sessionID+".jsonl")
	files, err := filepath.Glob(pattern)
	if err != nil {
		return nil, fmt.Errorf("glob claude transcript files: %w", err)
	}
	return files, nil
}

func claudeProjectsDir() string {
	homeDir, err := os.UserHomeDir()
	if err != nil {
		return filepath.Join(".claude", "projects")
	}
	return filepath.Join(homeDir, ".claude", "projects")
}
