package processor

import (
	"fmt"
)

// API handles phase execution requests.
type API struct {
	orch  *Orchestrator
	execs *ExecutorRegistry
}

// NewAPI creates a new phase API handler.
func NewAPI(orch *Orchestrator, execs *ExecutorRegistry) *API {
	return &API{
		orch:  orch,
		execs: execs,
	}
}

// Execute handles a phase execution request.
func (api *API) Execute(recordID, phaseName string) (Record, error) {
	// Check if phase can run
	canRun, err := api.orch.CanRun(recordID, phaseName)
	if err != nil {
		return nil, err
	}

	if !canRun {
		return nil, err
	}

	// Get executor
	exec := api.execs.Get(phaseName)
	if exec == nil {
		return nil, err
	}

	// Get record
	record, err := api.orch.Get(recordID)
	if err != nil {
		return nil, err
	}

	// Execute phase
	result := exec.Execute(record)
	if result.Error != nil {
		// Mark as failed
		api.orch.MarkFailed(recordID, result.Error.Error())
		return nil, result.Error
	}

	// Update state
	if err := api.orch.UpdateState(recordID, phaseName, result.Data); err != nil {
		return nil, err
	}

	// Return updated record
	return api.orch.Get(recordID)
}

// Get retrieves record status.
func (api *API) Get(recordID string) (Record, error) {
	return api.orch.Get(recordID)
}

// Advance executes the current phase and advances on success.
func (api *API) Advance(recordID string) (Record, error) {
	// Get record
	record, err := api.orch.Get(recordID)
	if err != nil {
		return nil, err
	}

	// Determine which phase to execute
	var phaseName string
	currentPhase := record.GetCurrentPhase()

	if currentPhase == nil {
		// No current phase - start with first phase
		if len(api.orch.order) == 0 {
			return nil, fmt.Errorf("no phases registered")
		}
		phaseName = api.orch.order[0]
		// Set current phase
		record.SetCurrentPhase(&phaseName)
		record.SetStatus("processing")
		if err := api.orch.store.Save(record); err != nil {
			return nil, err
		}
	} else {
		phaseName = *currentPhase
	}

	// Get executor
	exec := api.execs.Get(phaseName)
	if exec == nil {
		return nil, fmt.Errorf("executor not found for phase: %s", phaseName)
	}

	// Execute phase
	result := exec.Execute(record)
	if result.Error != nil {
		// Mark as failed
		api.orch.MarkFailed(recordID, result.Error.Error())
		return nil, result.Error
	}

	// Update state (this will advance current_phase)
	if err := api.orch.UpdateState(recordID, phaseName, result.Data); err != nil {
		return nil, err
	}

	// Return updated record
	return api.orch.Get(recordID)
}

// Rerun rolls back to the last completed phase and re-executes it.
func (api *API) Rerun(recordID string) (Record, error) {
	// Get record
	record, err := api.orch.Get(recordID)
	if err != nil {
		return nil, err
	}

	completedPhases := record.GetCompletedPhases()
	if len(completedPhases) == 0 {
		return nil, fmt.Errorf("no completed phases to rerun")
	}

	// Get last completed phase
	lastPhase := completedPhases[len(completedPhases)-1]

	// Remove from completed phases
	completedPhases = completedPhases[:len(completedPhases)-1]

	// Update record state
	record.SetCurrentPhase(&lastPhase)
	record.SetStatus("processing")

	// Manually update completed_phases
	// We need to save this state before executing
	if err := api.orch.store.Save(record); err != nil {
		return nil, err
	}

	// Get executor
	exec := api.execs.Get(lastPhase)
	if exec == nil {
		return nil, fmt.Errorf("executor not found for phase: %s", lastPhase)
	}

	// Execute phase
	result := exec.Execute(record)
	if result.Error != nil {
		// Mark as failed
		api.orch.MarkFailed(recordID, result.Error.Error())
		return nil, result.Error
	}

	// Update state (this will advance current_phase)
	if err := api.orch.UpdateState(recordID, lastPhase, result.Data); err != nil {
		return nil, err
	}

	// Return updated record
	return api.orch.Get(recordID)
}
