-- Migration: Agent Fleet Infrastructure
-- Adds tables for multi-instance OpenClaw orchestration
-- Run after base schema exists

-- ============================================
-- INSTANCE REGISTRY
-- ============================================
CREATE TABLE IF NOT EXISTS instances (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL UNIQUE,
    role VARCHAR(50) NOT NULL CHECK (role IN ('gateway', 'department', 'task_worker', 'user_session')),
    parent_id UUID REFERENCES instances(id) ON DELETE SET NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'starting' CHECK (status IN ('starting', 'running', 'paused', 'stopped', 'error')),
    config JSONB NOT NULL DEFAULT '{}',
    capabilities JSONB NOT NULL DEFAULT '[]',
    handles JSONB NOT NULL DEFAULT '[]',  -- Projects/channels this instance handles
    max_children INT DEFAULT 5,
    max_workers INT DEFAULT 10,
    idle_timeout_minutes INT DEFAULT 30,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    last_heartbeat_at TIMESTAMPTZ,
    metadata JSONB DEFAULT '{}'
);

CREATE INDEX idx_instances_role ON instances(role);
CREATE INDEX idx_instances_parent ON instances(parent_id);
CREATE INDEX idx_instances_status ON instances(status);

-- ============================================
-- SESSIONS (User/Project Sessions)
-- ============================================
CREATE TABLE IF NOT EXISTS sessions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
    session_key VARCHAR(255) NOT NULL UNIQUE,
    user_id VARCHAR(255),  -- Discord user ID, etc.
    channel_id VARCHAR(255),  -- Discord channel ID
    project_context VARCHAR(255),  -- Which project this session is for
    status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'idle', 'paused', 'closed')),
    context_window JSONB DEFAULT '[]',  -- Conversation history
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    closed_at TIMESTAMPTZ
);

CREATE INDEX idx_sessions_instance ON sessions(instance_id);
CREATE INDEX idx_sessions_user ON sessions(user_id);
CREATE INDEX idx_sessions_channel ON sessions(channel_id);
CREATE INDEX idx_sessions_status ON sessions(status);

-- ============================================
-- SESSION SUMMARIES (For RAG Context)
-- ============================================
CREATE TABLE IF NOT EXISTS session_summaries (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    session_id UUID REFERENCES sessions(id) ON DELETE CASCADE,
    instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
    summary_type VARCHAR(50) NOT NULL CHECK (summary_type IN ('decision', 'key_info', 'action_item', 'lesson', 'milestone')),
    content TEXT NOT NULL,
    embedding VECTOR(1024),  -- bge-m3 dimension
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_summaries_instance ON session_summaries(instance_id);
CREATE INDEX idx_summaries_type ON session_summaries(summary_type);
CREATE INDEX idx_summaries_session ON session_summaries(session_id);

-- pgvector index for semantic search
CREATE INDEX IF NOT EXISTS idx_summaries_embedding ON session_summaries 
USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

-- ============================================
-- EVENT LOG (Audit Trail)
-- ============================================
CREATE TABLE IF NOT EXISTS event_log (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    instance_id UUID REFERENCES instances(id) ON DELETE SET NULL,
    session_id UUID REFERENCES sessions(id) ON DELETE SET NULL,
    event_type VARCHAR(100) NOT NULL,
    event_data JSONB DEFAULT '{}',
    severity VARCHAR(20) NOT NULL DEFAULT 'info' CHECK (severity IN ('debug', 'info', 'warn', 'error')),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_event_log_instance ON event_log(instance_id);
CREATE INDEX idx_event_log_session ON event_log(session_id);
CREATE INDEX idx_event_log_type ON event_log(event_type);
CREATE INDEX idx_event_log_severity ON event_log(severity);
CREATE INDEX idx_event_log_created ON event_log(created_at);

-- ============================================
-- CHANNEL MAPPINGS (Routing)
-- ============================================
CREATE TABLE IF NOT EXISTS channel_mappings (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    channel_id VARCHAR(255) NOT NULL UNIQUE,
    channel_type VARCHAR(50) NOT NULL,  -- discord, telegram, etc.
    instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
    project_context VARCHAR(255),
    skills JSONB DEFAULT '[]',  -- Allowed skills for this channel
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_channel_mappings_instance ON channel_mappings(instance_id);
CREATE INDEX idx_channel_mappings_channel ON channel_mappings(channel_id);

-- ============================================
-- TASK QUEUE (For Worker Spawning)
-- ============================================
CREATE TABLE IF NOT EXISTS task_queue (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    task_type VARCHAR(50) NOT NULL,
    parent_instance_id UUID REFERENCES instances(id) ON DELETE SET NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'claimed', 'running', 'completed', 'failed', 'cancelled')),
    task_data JSONB NOT NULL DEFAULT '{}',
    result_data JSONB,
    assigned_worker_id UUID REFERENCES instances(id) ON DELETE SET NULL,
    priority INT DEFAULT 0,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    started_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ
);

CREATE INDEX idx_task_queue_status ON task_queue(status);
CREATE INDEX idx_task_queue_parent ON task_queue(parent_instance_id);
CREATE INDEX idx_task_queue_priority ON task_queue(priority DESC, created_at);

-- ============================================
-- DEFAULT INSTANCES (Seed Data)
-- ============================================
INSERT INTO instances (name, role, status, config, capabilities, handles, max_children, max_workers)
VALUES 
    ('jarvis-main', 'gateway', 'running', 
     '{"skills": ["orchestration", "mosaic-bootstrap", "all-projects-access"]}',
     '["spawn", "kill", "route", "delegate"]',
     '[]', 5, 10),
    ('jarvis-projects', 'department', 'running',
     '{"skills": ["coding-agent", "next-best-practices", "nestjs-best-practices", "fastapi"]}',
     '["spawn-workers", "code-review", "ci-cd"]',
     '["mosaic-stack", "sagephr", "lark-path"]', 3, 5),
    ('jarvis-research', 'department', 'running',
     '{"skills": ["web-search", "web-fetch", "brainstorming"]}',
     '["research", "discovery", "analysis"]',
     '[]', 2, 3),
    ('jarvis-operations', 'department', 'running',
     '{"skills": ["monitoring", "healthcheck", "maintenance"]}',
     '["monitoring", "maintenance", "alerts"]',
     '[]', 2, 3)
ON CONFLICT (name) DO NOTHING;
