-- Migration: Add Pack Runtime Environments
-- Description: Adds support for per-pack isolated runtime environments with installer metadata
-- Version: 20260203000002
-- Note: runtime.installers column is defined in migration 20250101000002_pack_system.sql

-- ============================================================================
-- PART 1: Create pack_environment table
-- ============================================================================

-- Pack environment table
CREATE TABLE IF NOT EXISTS pack_environment (
    id BIGSERIAL PRIMARY KEY,
    pack BIGINT NOT NULL REFERENCES pack(id) ON DELETE CASCADE,
    pack_ref TEXT NOT NULL,
    runtime BIGINT NOT NULL REFERENCES runtime(id) ON DELETE CASCADE,
    runtime_ref TEXT NOT NULL,
    env_path TEXT NOT NULL,
    status pack_environment_status_enum NOT NULL DEFAULT 'pending',
    installed_at TIMESTAMPTZ,
    last_verified TIMESTAMPTZ,
    install_log TEXT,
    install_error TEXT,
    metadata JSONB DEFAULT '{}'::jsonb,
    created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE(pack, runtime)
);

-- Indexes
CREATE INDEX IF NOT EXISTS idx_pack_environment_pack ON pack_environment(pack);
CREATE INDEX IF NOT EXISTS idx_pack_environment_runtime ON pack_environment(runtime);
CREATE INDEX IF NOT EXISTS idx_pack_environment_status ON pack_environment(status);
CREATE INDEX IF NOT EXISTS idx_pack_environment_pack_ref ON pack_environment(pack_ref);
CREATE INDEX IF NOT EXISTS idx_pack_environment_runtime_ref ON pack_environment(runtime_ref);
CREATE INDEX IF NOT EXISTS idx_pack_environment_pack_runtime ON pack_environment(pack, runtime);

-- Trigger for updated timestamp
CREATE TRIGGER update_pack_environment_updated
    BEFORE UPDATE ON pack_environment
    FOR EACH ROW
    EXECUTE FUNCTION update_updated_column();

-- Comments
COMMENT ON TABLE pack_environment IS 'Tracks pack-specific runtime environments for dependency isolation';
COMMENT ON COLUMN pack_environment.pack IS 'Pack that owns this environment';
COMMENT ON COLUMN pack_environment.pack_ref IS 'Pack reference for quick lookup';
COMMENT ON COLUMN pack_environment.runtime IS 'Runtime used for this environment';
COMMENT ON COLUMN pack_environment.runtime_ref IS 'Runtime reference for quick lookup';
COMMENT ON COLUMN pack_environment.env_path IS 'Filesystem path to the environment directory (e.g., /opt/attune/packenvs/mypack/python)';
COMMENT ON COLUMN pack_environment.status IS 'Current installation status';
COMMENT ON COLUMN pack_environment.installed_at IS 'When the environment was successfully installed';
COMMENT ON COLUMN pack_environment.last_verified IS 'Last time the environment was verified as working';
COMMENT ON COLUMN pack_environment.install_log IS 'Installation output logs';
COMMENT ON COLUMN pack_environment.install_error IS 'Error message if installation failed';
COMMENT ON COLUMN pack_environment.metadata IS 'Additional metadata (installed packages, versions, etc.)';

-- ============================================================================
-- PART 2: Update existing runtimes with installer metadata
-- ============================================================================

-- Python runtime installers
UPDATE runtime
SET installers = jsonb_build_object(
    'base_path_template', '/opt/attune/packenvs/{pack_ref}/{runtime_name_lower}',
    'installers', jsonb_build_array(
        jsonb_build_object(
            'name', 'create_venv',
            'description', 'Create Python virtual environment',
            'command', 'python3',
            'args', jsonb_build_array('-m', 'venv', '{env_path}'),
            'cwd', '{pack_path}',
            'env', jsonb_build_object(),
            'order', 1,
            'optional', false
        ),
        jsonb_build_object(
            'name', 'upgrade_pip',
            'description', 'Upgrade pip to latest version',
            'command', '{env_path}/bin/pip',
            'args', jsonb_build_array('install', '--upgrade', 'pip'),
            'cwd', '{pack_path}',
            'env', jsonb_build_object(),
            'order', 2,
            'optional', true
        ),
        jsonb_build_object(
            'name', 'install_requirements',
            'description', 'Install pack Python dependencies',
            'command', '{env_path}/bin/pip',
            'args', jsonb_build_array('install', '-r', '{pack_path}/requirements.txt'),
            'cwd', '{pack_path}',
            'env', jsonb_build_object(),
            'order', 3,
            'optional', false,
            'condition', jsonb_build_object(
                'file_exists', '{pack_path}/requirements.txt'
            )
        )
    ),
    'executable_templates', jsonb_build_object(
        'python', '{env_path}/bin/python',
        'pip', '{env_path}/bin/pip'
    )
)
WHERE ref = 'core.python';

-- Node.js runtime installers
UPDATE runtime
SET installers = jsonb_build_object(
    'base_path_template', '/opt/attune/packenvs/{pack_ref}/{runtime_name_lower}',
    'installers', jsonb_build_array(
        jsonb_build_object(
            'name', 'npm_install',
            'description', 'Install Node.js dependencies',
            'command', 'npm',
            'args', jsonb_build_array('install', '--prefix', '{env_path}'),
            'cwd', '{pack_path}',
            'env', jsonb_build_object(
                'NODE_PATH', '{env_path}/node_modules'
            ),
            'order', 1,
            'optional', false,
            'condition', jsonb_build_object(
                'file_exists', '{pack_path}/package.json'
            )
        )
    ),
    'executable_templates', jsonb_build_object(
        'node', 'node',
        'npm', 'npm'
    ),
    'env_vars', jsonb_build_object(
        'NODE_PATH', '{env_path}/node_modules'
    )
)
WHERE ref = 'core.nodejs';

-- Shell runtime (no environment needed, uses system shell)
UPDATE runtime
SET installers = jsonb_build_object(
    'base_path_template', '/opt/attune/packenvs/{pack_ref}/{runtime_name_lower}',
    'installers', jsonb_build_array(),
    'executable_templates', jsonb_build_object(
        'sh', 'sh',
        'bash', 'bash'
    ),
    'requires_environment', false
)
WHERE ref = 'core.shell';

-- Native runtime (no environment needed, binaries are standalone)
UPDATE runtime
SET installers = jsonb_build_object(
    'base_path_template', '/opt/attune/packenvs/{pack_ref}/{runtime_name_lower}',
    'installers', jsonb_build_array(),
    'executable_templates', jsonb_build_object(),
    'requires_environment', false
)
WHERE ref = 'core.native';

-- Built-in sensor runtime (internal, no environment)
UPDATE runtime
SET installers = jsonb_build_object(
    'installers', jsonb_build_array(),
    'requires_environment', false
)
WHERE ref = 'core.sensor.builtin';

-- ============================================================================
-- PART 3: Add helper functions
-- ============================================================================

-- Function to get environment path for a pack/runtime combination
CREATE OR REPLACE FUNCTION get_pack_environment_path(p_pack_ref TEXT, p_runtime_ref TEXT)
RETURNS TEXT AS $$
DECLARE
    v_runtime_name TEXT;
    v_base_template TEXT;
    v_result TEXT;
BEGIN
    -- Get runtime name and base path template
    SELECT
        LOWER(name),
        installers->>'base_path_template'
    INTO v_runtime_name, v_base_template
    FROM runtime
    WHERE ref = p_runtime_ref;

    IF v_base_template IS NULL THEN
        v_base_template := '/opt/attune/packenvs/{pack_ref}/{runtime_name_lower}';
    END IF;

    -- Replace template variables
    v_result := v_base_template;
    v_result := REPLACE(v_result, '{pack_ref}', p_pack_ref);
    v_result := REPLACE(v_result, '{runtime_ref}', p_runtime_ref);
    v_result := REPLACE(v_result, '{runtime_name_lower}', v_runtime_name);

    RETURN v_result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;

COMMENT ON FUNCTION get_pack_environment_path IS 'Calculate the filesystem path for a pack runtime environment';

-- Function to check if a runtime requires an environment
CREATE OR REPLACE FUNCTION runtime_requires_environment(p_runtime_ref TEXT)
RETURNS BOOLEAN AS $$
DECLARE
    v_requires BOOLEAN;
BEGIN
    SELECT COALESCE((installers->>'requires_environment')::boolean, true)
    INTO v_requires
    FROM runtime
    WHERE ref = p_runtime_ref;

    RETURN COALESCE(v_requires, false);
END;
$$ LANGUAGE plpgsql STABLE;

COMMENT ON FUNCTION runtime_requires_environment IS 'Check if a runtime needs a pack-specific environment';

-- ============================================================================
-- PART 4: Create view for environment status
-- ============================================================================

CREATE OR REPLACE VIEW v_pack_environment_status AS
SELECT
    pe.id,
    pe.pack,
    p.ref AS pack_ref,
    p.label AS pack_name,
    pe.runtime,
    r.ref AS runtime_ref,
    r.name AS runtime_name,
    pe.env_path,
    pe.status,
    pe.installed_at,
    pe.last_verified,
    CASE
        WHEN pe.status = 'ready' AND pe.last_verified < NOW() - INTERVAL '7 days' THEN true
        ELSE false
    END AS needs_verification,
    CASE
        WHEN pe.status = 'ready' THEN 'healthy'
        WHEN pe.status = 'failed' THEN 'unhealthy'
        WHEN pe.status IN ('pending', 'installing') THEN 'provisioning'
        WHEN pe.status = 'outdated' THEN 'needs_update'
        ELSE 'unknown'
    END AS health_status,
    pe.install_error,
    pe.created,
    pe.updated
FROM pack_environment pe
JOIN pack p ON pe.pack = p.id
JOIN runtime r ON pe.runtime = r.id;

COMMENT ON VIEW v_pack_environment_status IS 'Consolidated view of pack environment status with health indicators';

-- ============================================================================
-- SUMMARY
-- ============================================================================

-- Display summary of changes
DO $$
BEGIN
    RAISE NOTICE 'Pack environment system migration complete.';
    RAISE NOTICE '';
    RAISE NOTICE 'New table: pack_environment (tracks installed environments)';
    RAISE NOTICE 'New column: runtime.installers (environment setup instructions)';
    RAISE NOTICE 'New functions: get_pack_environment_path, runtime_requires_environment';
    RAISE NOTICE 'New view: v_pack_environment_status';
    RAISE NOTICE '';
    RAISE NOTICE 'Environment paths will be: /opt/attune/packenvs/{pack_ref}/{runtime}';
END $$;
