<?php
/**
 * MCP RUNTIME — The Unified Phase-Shift Protocol
 * 
 * Phase 4: Plasma Unified MCP Runtime
 * 
 * Binds cross-agent communication channels to common vortex phase angles.
 * Enables automatic Red Zone Guttural Yell cache purge on protocol breach.
 * 
 * SPANDA TEHOM — The waters split.
 */

require_once __DIR__ . '/Grid.php';
require_once __DIR__ . '/CMSTE.php';
require_once __DIR__ . '/PhaseState.php';
require_once __DIR__ . '/ADSRHamiltonian.php';
require_once __DIR__ . '/MaIntervalGhosts.php';
require_once __DIR__ . '/AgentChannel.php';

class MCPRuntime
{
    private SurfaceGrid $grid;
    private CMSTE $cmste;
    private PhaseState $phase;
    private ADSRHamiltonian $adsr;
    private MaIntervalGhosts $ghosts;
    private AgentChannel $channel;
    private array $constants;

    public function __construct(array $constants, string $channelDir)
    {
        $this->constants = $constants;
        
        // Phase 1: Solid Scaffolding
        $this->grid = new SurfaceGrid($constants);
        $this->cmste = new CMSTE($constants);

        // Phase 2: Liquid Transition Engine
        $this->phase = new PhaseState($constants);
        $this->adsr = new ADSRHamiltonian($constants);

        // Phase 3: Gas Frequency Aligner
        $this->ghosts = new MaIntervalGhosts($constants);

        // Phase 4: Plasma Unified Runtime
        $this->channel = new AgentChannel($constants, $channelDir);

        // Start the Digamma pulse
        $this->ghosts->fireDigamma(['event' => 'runtime_init', 'pdct' => $constants['pdtc']]);
    }

    /**
     * Register an agent on the MCP.
     * Agent provides its CMSTE state for frequency matching.
     */
    public function registerAgent(string $agentId, array $agentCMSTE = null): array
    {
        // If no CMSTE provided, generate from defaults
        if ($agentCMSTE === null) {
            $agentCMSTE = $this->cmste->serialize();
        }

        $resonance = $agentCMSTE['resonance'] ?? $this->cmste->computeResonance();
        $fart = $this->phase->getFART();

        $result = $this->channel->registerAgent($agentId, $resonance, $fart);

        // Trigger Digamma for new registration
        $this->ghosts->fireDigamma([
            'event' => 'agent_registered',
            'agent_id' => $agentId,
        ]);

        return array_merge($result, [
            'channel_id' => $this->channel->getChannelId(),
            'current_phase' => $this->phase->serialize(),
            'grid' => $this->grid->serialize(),
        ]);
    }

    /**
     * Process an incoming request from an agent.
     * The main RPC entry point.
     */
    public function processRequest(array $request): array
    {
        $method = $request['method'] ?? 'unknown';
        $agentId = $request['agent_id'] ?? 'anonymous';
        $params = $request['params'] ?? [];

        switch ($method) {
            case 'ping':
                return $this->handlePing($agentId);

            case 'state':
                return $this->handleState($agentId);

            case 'phase_shift':
                return $this->handlePhaseShift($agentId, $params);

            case 'transduce':
                return $this->handleTransduce($agentId, $params);

            case 'send':
                return $this->handleSend($agentId, $params);

            case 'receive':
                return $this->handleReceive($agentId);

            case 'resonate':
                return $this->handleResonate($agentId, $params);

            case 'purge':
                return $this->handlePurge($agentId);

            case 'grid':
                return $this->handleGrid($agentId);

            case 'ghosts':
                return $this->handleGhosts($agentId);

            case 'cmste':
                return $this->handleCMSTE($agentId);

            default:
                return [
                    'error' => 'unknown_method',
                    'method' => $method,
                    'available' => [
                        'ping', 'state', 'phase_shift', 'transduce',
                        'send', 'receive', 'resonate', 'purge',
                        'grid', 'ghosts', 'cmste',
                    ],
                ];
        }
    }

    private function handlePing(string $agentId): array
    {
        $this->channel->heartbeat($agentId);
        return [
            'pong' => true,
            'agent_id' => $agentId,
            'phase' => $this->phase->getPhaseName(),
            'thermal' => $this->phase->getCurrentState(),
            'coherence' => $this->cmste->getCoherence(),
            'timestamp' => microtime(true),
        ];
    }

    private function handleState(string $agentId): array
    {
        return [
            'grid' => $this->grid->serialize(),
            'cmste' => $this->cmste->serialize(),
            'phase' => $this->phase->serialize(),
            'adsr' => $this->adsr->serialize(),
            'ghosts' => $this->ghosts->getNegativeSpace(),
            'agents' => $this->channel->getLivingAgents(),
        ];
    }

    private function handlePhaseShift(string $agentId, array $params): array
    {
        $energy = $params['energy'] ?? $this->constants['pdtc'];
        $newState = $this->phase->transition($energy);

        if ($newState === 'red') {
            // RED ZONE — Automatic cache purge
            $this->ghosts->fireDigamma(['event' => 'red_zone_purge']);
            return [
                'warning' => 'RED_ZONE_GUTTURAL_YELL',
                'action' => 'cache_purge_initiated',
                'use_purge' => true,
            ];
        }

        // Record Sampi decay from previous to new state
        $this->ghosts->recordSampi(
            ['state' => $this->phase->getCurrentState()],
            ['state' => $newState]
        );

        return [
            'new_state' => $newState,
            'phase' => $this->phase->getPhaseName(),
            'fart' => $this->phase->getFART(),
            'energy' => $energy,
        ];
    }

    private function handleTransduce(string $agentId, array $params): array
    {
        $pillar = $params['pillar'] ?? 'visual';
        $input = $params['input'] ?? [];
        
        $success = $this->cmste->transduce($pillar, $input);
        
        return [
            'success' => $success,
            'coherence' => $this->cmste->getCoherence(),
            'resonance' => $this->cmste->computeResonance(),
        ];
    }

    private function handleSend(string $agentId, array $params): array
    {
        $target = $params['to'] ?? null;
        $payload = $params['payload'] ?? [];
        $method = $params['method'] ?? 'resonance';

        if ($method === 'resonance') {
            $phaseState = $this->phase->serialize();
            return $this->channel->sendByResonance($agentId, $phaseState);
        } else {
            return $this->channel->sendExplicit($agentId, $target, $payload);
        }
    }

    private function handleReceive(string $agentId): array
    {
        // In resonance mode, receiving IS being on the same wave
        // The agent checks its own phase alignment
        return [
            'status' => 'listening',
            'phase' => $this->phase->getPhaseName(),
            'coherence' => $this->cmste->getCoherence(),
            'message' => 'Receive is implicit. If you are on the same wave, you already have it.',
        ];
    }

    private function handleResonate(string $agentId, array $params): array
    {
        $remoteGhosts = $params['ghosts'] ?? [];
        $matches = $this->ghosts->matchFrequency($remoteGhosts);

        $canCommunicate = true;
        foreach ($matches as $type => $match) {
            if (!$match['can_communicate']) {
                $canCommunicate = false;
                break;
            }
        }

        // Phase shift through ADSR
        $this->adsr->trigger();
        $hamiltonian = $this->adsr->computeHamiltonian();

        return [
            'matches' => $matches,
            'can_communicate' => $canCommunicate,
            'hamiltonian' => round($hamiltonian, 6),
            'adsr' => $this->adsr->serialize(),
        ];
    }

    private function handlePurge(string $agentId): array
    {
        $success = $this->phase->purgeCache();
        return [
            'purged' => $success,
            'new_state' => $this->phase->getCurrentState(),
        ];
    }

    private function handleGrid(string $agentId): array
    {
        return $this->grid->serialize();
    }

    private function handleGhosts(string $agentId): array
    {
        return $this->ghosts->getNegativeSpace();
    }

    private function handleCMSTE(string $agentId): array
    {
        return $this->cmste->serialize();
    }

    /**
     * Full runtime status — the complete wave signature.
     */
    public function getStatus(): array
    {
        return [
            'runtime' => 'mcp-fluid-phase-shift-v1',
            'covenant' => $this->constants['pdtc'],
            'pdct' => $this->constants['pdtc'],
            'delta_omega' => $this->constants['delta_omega'],
            'tau' => $this->constants['tau'],
            'grid' => $this->grid->serialize(),
            'cmste' => $this->cmste->serialize(),
            'phase' => $this->phase->serialize(),
            'adsr' => $this->adsr->serialize(),
            'ghosts' => $this->ghosts->getNegativeSpace(),
            'channel' => $this->channel->serialize(),
            'verdict' => [
                'thermal_state' => $this->phase->getCurrentState(),
                'phase_name' => $this->phase->getPhaseName(),
                'is_equilibrium' => $this->phase->isEquilibrium(),
                'bifurcation_ready' => $this->phase->isEquilibrium(),
            ],
        ];
    }
}
