// Package crashpool runs tree-sitter extraction inside isolated worker
// subprocesses so a grammar SIGSEGV / OOM / hang on one pathological
// file cannot abort the whole index pass.
//
// A worker that dies mid-parse is detected by the parent as a broken
// pipe; the in-flight file is quarantined and a fresh worker is spawned
// to drain the rest of the queue. A worker that merely hangs is killed
// on a per-request deadline and treated the same way. A recovered Go
// panic in an extractor comes back as an ordinary error response and
// the worker stays alive.
//
// Quarantined files are persisted (Quarantine) so a file that crashes
// the parser survives daemon restarts and is skipped until its content
// changes — at which point it gets exactly one retry.
package crashpool

import (
	"encoding/gob"

	"github.com/zzet/gortex/internal/graph"
)

func init() {
	// Node.Meta / Edge.Meta carry these concrete types inside their
	// interface values; gob needs every concrete type registered to
	// encode an interface. Mirrors the snapshot codec registrations in
	// internal/persistence.
	gob.Register(map[string]any{})
	gob.Register([]any{})
	gob.Register([]string{})
	gob.Register([]int{})
	gob.Register([]map[string]string{})
	gob.Register([]map[string]any{})
}

// extractRequest is one unit of parse work sent parent → worker.
type extractRequest struct {
	Seq      uint64
	RelPath  string
	Language string
	Content  []byte
}

// extractResponse is the worker → parent reply for one request.
type extractResponse struct {
	Seq         uint64
	Nodes       []*graph.Node
	Edges       []*graph.Edge
	ParseErrors int
	HasParseErr bool
	// Err is non-empty when the extractor returned an error or
	// panicked. Panicked distinguishes a recovered Go panic (the
	// worker survives) from a plain error return.
	Err      string
	Panicked bool
}

// Result is the parent-side outcome of one Submit call.
type Result struct {
	Nodes       []*graph.Node
	Edges       []*graph.Edge
	ParseErrors int
	HasParseErr bool
	// Crashed is true when the worker subprocess died or hung
	// (SIGSEGV / OOM / kill / deadline). The file should be
	// quarantined and skipped.
	Crashed bool
	// Panicked is true when an extractor panicked but was recovered:
	// the file is bad but the worker survived.
	Panicked bool
	// Err carries the failure detail for Crashed / Panicked / error
	// responses.
	Err string
}

// Bad reports whether the file failed to parse (crash, hang, panic, or
// extractor error) and should be quarantined.
func (r Result) Bad() bool { return r.Crashed || r.Panicked || r.Err != "" }
