-- =====================================================
-- BotKonzept - Installer JSON API Extension
-- =====================================================
-- Extends the database schema to store and expose installer JSON data
-- safely to frontend clients (without secrets)

-- =====================================================
-- Step 1: Add installer_json column to instances table
-- =====================================================

-- Add column to store the complete installer JSON
ALTER TABLE instances 
ADD COLUMN IF NOT EXISTS installer_json JSONB DEFAULT '{}'::jsonb;

-- Create index for faster JSON queries
CREATE INDEX IF NOT EXISTS idx_instances_installer_json ON instances USING gin(installer_json);

-- Add comment
COMMENT ON COLUMN instances.installer_json IS 'Complete installer JSON output from install.sh (includes secrets - use api.instance_config view for safe access)';

-- =====================================================
-- Step 2: Create safe API view (NON-SECRET data only)
-- =====================================================

-- Create API schema if it doesn't exist
CREATE SCHEMA IF NOT EXISTS api;

-- Grant usage on api schema
GRANT USAGE ON SCHEMA api TO anon, authenticated, service_role;

-- Create view that exposes only safe (non-secret) installer data
CREATE OR REPLACE VIEW api.instance_config AS
SELECT 
    i.id,
    i.customer_id,
    i.lxc_id as ctid,
    i.hostname,
    i.fqdn,
    i.ip,
    i.vlan,
    i.status,
    i.created_at,
    -- Extract safe URLs from installer_json
    jsonb_build_object(
        'n8n_internal', i.installer_json->'urls'->>'n8n_internal',
        'n8n_external', i.installer_json->'urls'->>'n8n_external',
        'postgrest', i.installer_json->'urls'->>'postgrest',
        'chat_webhook', i.installer_json->'urls'->>'chat_webhook',
        'chat_internal', i.installer_json->'urls'->>'chat_internal',
        'upload_form', i.installer_json->'urls'->>'upload_form',
        'upload_form_internal', i.installer_json->'urls'->>'upload_form_internal'
    ) as urls,
    -- Extract safe Supabase data (NO service_role_key, NO jwt_secret)
    jsonb_build_object(
        'url_external', i.installer_json->'supabase'->>'url_external',
        'anon_key', i.installer_json->'supabase'->>'anon_key'
    ) as supabase,
    -- Extract Ollama URL (safe)
    jsonb_build_object(
        'url', i.installer_json->'ollama'->>'url',
        'model', i.installer_json->'ollama'->>'model',
        'embedding_model', i.installer_json->'ollama'->>'embedding_model'
    ) as ollama,
    -- Customer info (joined)
    c.email as customer_email,
    c.first_name,
    c.last_name,
    c.company,
    c.status as customer_status
FROM instances i
JOIN customers c ON i.customer_id = c.id
WHERE i.status = 'active' AND i.deleted_at IS NULL;

-- Add comment
COMMENT ON VIEW api.instance_config IS 'Safe API view for instance configuration - exposes only non-secret data from installer JSON';

-- =====================================================
-- Step 3: Row Level Security (RLS) for API view
-- =====================================================

-- Enable RLS on the view (inherited from base table)
-- Customers can only see their own instance config

-- Policy: Allow customers to see their own instance config
CREATE POLICY instance_config_select_own ON instances
    FOR SELECT
    USING (
        -- Allow if customer_id matches authenticated user
        customer_id::text = auth.uid()::text
        OR
        -- Allow service_role to see all (for n8n workflows)
        auth.jwt()->>'role' = 'service_role'
    );

-- Grant SELECT on api.instance_config view
GRANT SELECT ON api.instance_config TO anon, authenticated, service_role;

-- =====================================================
-- Step 4: Create function to get config by customer email
-- =====================================================

-- Function to get instance config by customer email (for public access)
CREATE OR REPLACE FUNCTION api.get_instance_config_by_email(customer_email_param TEXT)
RETURNS TABLE (
    id UUID,
    customer_id UUID,
    ctid BIGINT,
    hostname VARCHAR,
    fqdn VARCHAR,
    ip VARCHAR,
    vlan INTEGER,
    status VARCHAR,
    created_at TIMESTAMPTZ,
    urls JSONB,
    supabase JSONB,
    ollama JSONB,
    customer_email VARCHAR,
    first_name VARCHAR,
    last_name VARCHAR,
    company VARCHAR,
    customer_status VARCHAR
) AS $$
BEGIN
    RETURN QUERY
    SELECT 
        ic.id,
        ic.customer_id,
        ic.ctid,
        ic.hostname,
        ic.fqdn,
        ic.ip,
        ic.vlan,
        ic.status,
        ic.created_at,
        ic.urls,
        ic.supabase,
        ic.ollama,
        ic.customer_email,
        ic.first_name,
        ic.last_name,
        ic.company,
        ic.customer_status
    FROM api.instance_config ic
    WHERE ic.customer_email = customer_email_param
    LIMIT 1;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Grant execute permission
GRANT EXECUTE ON FUNCTION api.get_instance_config_by_email(TEXT) TO anon, authenticated, service_role;

-- Add comment
COMMENT ON FUNCTION api.get_instance_config_by_email IS 'Get instance configuration by customer email - returns only non-secret data';

-- =====================================================
-- Step 5: Create function to get config by CTID
-- =====================================================

-- Function to get instance config by CTID (for internal use)
CREATE OR REPLACE FUNCTION api.get_instance_config_by_ctid(ctid_param BIGINT)
RETURNS TABLE (
    id UUID,
    customer_id UUID,
    ctid BIGINT,
    hostname VARCHAR,
    fqdn VARCHAR,
    ip VARCHAR,
    vlan INTEGER,
    status VARCHAR,
    created_at TIMESTAMPTZ,
    urls JSONB,
    supabase JSONB,
    ollama JSONB,
    customer_email VARCHAR,
    first_name VARCHAR,
    last_name VARCHAR,
    company VARCHAR,
    customer_status VARCHAR
) AS $$
BEGIN
    RETURN QUERY
    SELECT 
        ic.id,
        ic.customer_id,
        ic.ctid,
        ic.hostname,
        ic.fqdn,
        ic.ip,
        ic.vlan,
        ic.status,
        ic.created_at,
        ic.urls,
        ic.supabase,
        ic.ollama,
        ic.customer_email,
        ic.first_name,
        ic.last_name,
        ic.company,
        ic.customer_status
    FROM api.instance_config ic
    WHERE ic.ctid = ctid_param
    LIMIT 1;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Grant execute permission
GRANT EXECUTE ON FUNCTION api.get_instance_config_by_ctid(BIGINT) TO service_role;

-- Add comment
COMMENT ON FUNCTION api.get_instance_config_by_ctid IS 'Get instance configuration by CTID - for internal use only';

-- =====================================================
-- Step 6: Create public config endpoint (no auth required)
-- =====================================================

-- Function to get public config (for website registration form)
-- Returns only the registration webhook URL
CREATE OR REPLACE FUNCTION api.get_public_config()
RETURNS TABLE (
    registration_webhook_url TEXT,
    api_base_url TEXT
) AS $$
BEGIN
    RETURN QUERY
    SELECT 
        'https://api.botkonzept.de/webhook/botkonzept-registration'::TEXT as registration_webhook_url,
        'https://api.botkonzept.de'::TEXT as api_base_url;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Grant execute permission to everyone
GRANT EXECUTE ON FUNCTION api.get_public_config() TO anon, authenticated, service_role;

-- Add comment
COMMENT ON FUNCTION api.get_public_config IS 'Get public configuration for website (registration webhook URL)';

-- =====================================================
-- Step 7: Update install.sh integration
-- =====================================================

-- This SQL will be executed after instance creation
-- The install.sh script should call this function to store the installer JSON

CREATE OR REPLACE FUNCTION api.store_installer_json(
    customer_email_param TEXT,
    lxc_id_param BIGINT,
    installer_json_param JSONB
)
RETURNS JSONB AS $$
DECLARE
    instance_record RECORD;
    result JSONB;
BEGIN
    -- Find the instance by customer email and lxc_id
    SELECT i.id, i.customer_id INTO instance_record
    FROM instances i
    JOIN customers c ON i.customer_id = c.id
    WHERE c.email = customer_email_param
      AND i.lxc_id = lxc_id_param
    LIMIT 1;
    
    IF NOT FOUND THEN
        RETURN jsonb_build_object(
            'success', false,
            'error', 'Instance not found for customer email and LXC ID'
        );
    END IF;
    
    -- Update the installer_json column
    UPDATE instances
    SET installer_json = installer_json_param,
        updated_at = NOW()
    WHERE id = instance_record.id;
    
    -- Return success
    result := jsonb_build_object(
        'success', true,
        'instance_id', instance_record.id,
        'customer_id', instance_record.customer_id,
        'message', 'Installer JSON stored successfully'
    );
    
    RETURN result;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Grant execute permission to service_role only
GRANT EXECUTE ON FUNCTION api.store_installer_json(TEXT, BIGINT, JSONB) TO service_role;

-- Add comment
COMMENT ON FUNCTION api.store_installer_json IS 'Store installer JSON after instance creation - called by install.sh via n8n workflow';

-- =====================================================
-- Step 8: Create audit log entry for API access
-- =====================================================

-- Function to log API access
CREATE OR REPLACE FUNCTION api.log_config_access(
    customer_id_param UUID,
    access_type TEXT,
    ip_address_param INET DEFAULT NULL
)
RETURNS VOID AS $$
BEGIN
    INSERT INTO audit_log (
        customer_id,
        action,
        entity_type,
        performed_by,
        ip_address,
        metadata
    ) VALUES (
        customer_id_param,
        'api_config_access',
        'instance_config',
        'api_user',
        ip_address_param,
        jsonb_build_object('access_type', access_type)
    );
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Grant execute permission
GRANT EXECUTE ON FUNCTION api.log_config_access(UUID, TEXT, INET) TO anon, authenticated, service_role;

-- =====================================================
-- Step 9: Example queries for testing
-- =====================================================

-- Example 1: Get instance config by customer email
-- SELECT * FROM api.get_instance_config_by_email('max@beispiel.de');

-- Example 2: Get instance config by CTID
-- SELECT * FROM api.get_instance_config_by_ctid(769697636);

-- Example 3: Get public config
-- SELECT * FROM api.get_public_config();

-- Example 4: Store installer JSON (called by install.sh)
-- SELECT api.store_installer_json(
--     'max@beispiel.de',
--     769697636,
--     '{"ctid": 769697636, "urls": {...}, ...}'::jsonb
-- );

-- =====================================================
-- Step 10: PostgREST API Routes
-- =====================================================

-- After running this SQL, the following PostgREST routes will be available:
--
-- 1. GET /api/instance_config
--    - Returns all instance configs (filtered by RLS)
--    - Requires authentication
--
-- 2. POST /rpc/get_instance_config_by_email
--    - Body: {"customer_email_param": "max@beispiel.de"}
--    - Returns instance config for specific customer
--    - No authentication required (public)
--
-- 3. POST /rpc/get_instance_config_by_ctid
--    - Body: {"ctid_param": 769697636}
--    - Returns instance config for specific CTID
--    - Requires service_role authentication
--
-- 4. POST /rpc/get_public_config
--    - Body: {}
--    - Returns public configuration (registration webhook URL)
--    - No authentication required (public)
--
-- 5. POST /rpc/store_installer_json
--    - Body: {"customer_email_param": "...", "lxc_id_param": 123, "installer_json_param": {...}}
--    - Stores installer JSON after instance creation
--    - Requires service_role authentication

-- =====================================================
-- End of API Extension
-- =====================================================
