-- Migration 006: Add Public Lists Integration
-- Description: Adds blacklist/whitelist public sources with auto-sync support
-- Author: IDS System
-- Date: 2024-11-26
-- NOTE: Fully idempotent - safe to run multiple times

BEGIN;

-- ============================================================================
-- 1. CREATE NEW TABLES
-- ============================================================================

-- Public threat/whitelist sources configuration
CREATE TABLE IF NOT EXISTS public_lists (
    id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
    name TEXT NOT NULL,
    type TEXT NOT NULL CHECK (type IN ('blacklist', 'whitelist')),
    url TEXT NOT NULL,
    enabled BOOLEAN NOT NULL DEFAULT true,
    fetch_interval_minutes INTEGER NOT NULL DEFAULT 10,
    last_fetch TIMESTAMP,
    last_success TIMESTAMP,
    total_ips INTEGER NOT NULL DEFAULT 0,
    active_ips INTEGER NOT NULL DEFAULT 0,
    error_count INTEGER NOT NULL DEFAULT 0,
    last_error TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS public_lists_type_idx ON public_lists(type);
CREATE INDEX IF NOT EXISTS public_lists_enabled_idx ON public_lists(enabled);

-- Public blacklist IPs from external sources
CREATE TABLE IF NOT EXISTS public_blacklist_ips (
    id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
    ip_address TEXT NOT NULL,
    cidr_range TEXT,
    list_id VARCHAR NOT NULL REFERENCES public_lists(id) ON DELETE CASCADE,
    first_seen TIMESTAMP NOT NULL DEFAULT NOW(),
    last_seen TIMESTAMP NOT NULL DEFAULT NOW(),
    is_active BOOLEAN NOT NULL DEFAULT true
);

CREATE INDEX IF NOT EXISTS public_blacklist_ip_idx ON public_blacklist_ips(ip_address);
CREATE INDEX IF NOT EXISTS public_blacklist_list_idx ON public_blacklist_ips(list_id);
CREATE INDEX IF NOT EXISTS public_blacklist_active_idx ON public_blacklist_ips(is_active);

-- Create unique constraint only if not exists
DO $$ 
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_indexes 
        WHERE indexname = 'public_blacklist_ip_list_key'
    ) THEN
        CREATE UNIQUE INDEX public_blacklist_ip_list_key ON public_blacklist_ips(ip_address, list_id);
    END IF;
END $$;

-- ============================================================================
-- 2. ALTER EXISTING TABLES
-- ============================================================================

-- Extend detections table with public list source tracking
ALTER TABLE detections 
ADD COLUMN IF NOT EXISTS detection_source TEXT NOT NULL DEFAULT 'ml_model',
ADD COLUMN IF NOT EXISTS blacklist_id VARCHAR;

CREATE INDEX IF NOT EXISTS detection_source_idx ON detections(detection_source);

-- Add check constraint for valid detection sources
DO $$ 
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint 
        WHERE conname = 'detections_source_check'
    ) THEN
        ALTER TABLE detections 
        ADD CONSTRAINT detections_source_check 
        CHECK (detection_source IN ('ml_model', 'public_blacklist', 'hybrid'));
    END IF;
END $$;

-- Extend whitelist table with source tracking
ALTER TABLE whitelist
ADD COLUMN IF NOT EXISTS source TEXT NOT NULL DEFAULT 'manual',
ADD COLUMN IF NOT EXISTS list_id VARCHAR;

CREATE INDEX IF NOT EXISTS whitelist_source_idx ON whitelist(source);

-- Add check constraint for valid whitelist sources
DO $$ 
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint 
        WHERE conname = 'whitelist_source_check'
    ) THEN
        ALTER TABLE whitelist 
        ADD CONSTRAINT whitelist_source_check 
        CHECK (source IN ('manual', 'aws', 'gcp', 'cloudflare', 'iana', 'ntp', 'other'));
    END IF;
END $$;

-- ============================================================================
-- 3. UPDATE SCHEMA VERSION
-- ============================================================================

INSERT INTO schema_version (id, version, description)
VALUES (1, 6, 'Add public lists integration (blacklist/whitelist sources)')
ON CONFLICT (id) DO UPDATE 
SET version = 6, 
    description = 'Add public lists integration (blacklist/whitelist sources)',
    applied_at = NOW();

COMMIT;

SELECT 'Migration 006 completed successfully' as status;
