-- 052_audit_triggers.sql
-- Database Triggers for Audit Logging (BE-DB-014: Add database triggers for audit logging)
-- Create triggers to auto-log changes to audit_logs table

-- === HELPER FUNCTION ===
-- Function to create audit log entries from trigger context
CREATE OR REPLACE FUNCTION public.audit_trigger_function()
RETURNS TRIGGER AS $$
DECLARE
    v_user_id UUID;
    v_action TEXT;
    v_old_data JSONB;
    v_new_data JSONB;
BEGIN
    -- Determine action type
    IF TG_OP = 'INSERT' THEN
        v_action := 'create';
        v_new_data := to_jsonb(NEW);
        v_old_data := NULL;
        -- Try to get user_id from NEW record (common column names)
        IF NEW.creator_id IS NOT NULL THEN
            v_user_id := NEW.creator_id;
        ELSIF NEW.user_id IS NOT NULL THEN
            v_user_id := NEW.user_id;
        ELSE
            v_user_id := NULL;
        END IF;
    ELSIF TG_OP = 'UPDATE' THEN
        v_action := 'update';
        v_old_data := to_jsonb(OLD);
        v_new_data := to_jsonb(NEW);
        -- Try to get user_id from NEW record
        IF NEW.creator_id IS NOT NULL THEN
            v_user_id := NEW.creator_id;
        ELSIF NEW.user_id IS NOT NULL THEN
            v_user_id := NEW.user_id;
        ELSE
            v_user_id := NULL;
        END IF;
    ELSIF TG_OP = 'DELETE' THEN
        v_action := 'delete';
        v_old_data := to_jsonb(OLD);
        v_new_data := NULL;
        -- Try to get user_id from OLD record
        IF OLD.creator_id IS NOT NULL THEN
            v_user_id := OLD.creator_id;
        ELSIF OLD.user_id IS NOT NULL THEN
            v_user_id := OLD.user_id;
        ELSE
            v_user_id := NULL;
        END IF;
    END IF;

    -- Insert audit log entry
    INSERT INTO public.audit_logs (
        id,
        user_id,
        action,
        resource,
        resource_id,
        metadata,
        timestamp
    ) VALUES (
        gen_random_uuid(),
        v_user_id,
        v_action,
        TG_TABLE_NAME,
        CASE 
            WHEN TG_OP = 'DELETE' THEN (OLD.id)::UUID
            ELSE (NEW.id)::UUID
        END,
        jsonb_build_object(
            'operation', TG_OP,
            'old_data', v_old_data,
            'new_data', v_new_data,
            'table', TG_TABLE_NAME
        ),
        NOW()
    );

    -- Return appropriate record
    IF TG_OP = 'DELETE' THEN
        RETURN OLD;
    ELSE
        RETURN NEW;
    END IF;
END;
$$ LANGUAGE plpgsql;

COMMENT ON FUNCTION public.audit_trigger_function() IS 'Generic audit trigger function that logs INSERT, UPDATE, and DELETE operations to audit_logs table';

-- === TRIGGERS FOR USERS TABLE ===
DROP TRIGGER IF EXISTS audit_users_trigger ON public.users;
CREATE TRIGGER audit_users_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.users
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_users_trigger ON public.users IS 'Audit trigger for users table - logs all create, update, and delete operations';

-- === TRIGGERS FOR TRACKS TABLE ===
DROP TRIGGER IF EXISTS audit_tracks_trigger ON public.tracks;
CREATE TRIGGER audit_tracks_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.tracks
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_tracks_trigger ON public.tracks IS 'Audit trigger for tracks table - logs all create, update, and delete operations';

-- === TRIGGERS FOR PLAYLISTS TABLE ===
DROP TRIGGER IF EXISTS audit_playlists_trigger ON public.playlists;
CREATE TRIGGER audit_playlists_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.playlists
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_playlists_trigger ON public.playlists IS 'Audit trigger for playlists table - logs all create, update, and delete operations';

-- === TRIGGERS FOR PLAYLIST_TRACKS TABLE ===
DROP TRIGGER IF EXISTS audit_playlist_tracks_trigger ON public.playlist_tracks;
CREATE TRIGGER audit_playlist_tracks_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.playlist_tracks
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_playlist_tracks_trigger ON public.playlist_tracks IS 'Audit trigger for playlist_tracks table - logs all create, update, and delete operations';

-- === TRIGGERS FOR TRACK_LIKES TABLE ===
DROP TRIGGER IF EXISTS audit_track_likes_trigger ON public.track_likes;
CREATE TRIGGER audit_track_likes_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.track_likes
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_track_likes_trigger ON public.track_likes IS 'Audit trigger for track_likes table - logs all create, update, and delete operations';

-- === TRIGGERS FOR TRACK_COMMENTS TABLE ===
DROP TRIGGER IF EXISTS audit_track_comments_trigger ON public.track_comments;
CREATE TRIGGER audit_track_comments_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.track_comments
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_track_comments_trigger ON public.track_comments IS 'Audit trigger for track_comments table - logs all create, update, and delete operations';

-- === TRIGGERS FOR MARKETPLACE_PRODUCTS TABLE ===
-- Note: marketplace_products table may not exist yet
DO $$
BEGIN
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'marketplace_products'
    ) THEN
        DROP TRIGGER IF EXISTS audit_marketplace_products_trigger ON public.marketplace_products;
        CREATE TRIGGER audit_marketplace_products_trigger
            AFTER INSERT OR UPDATE OR DELETE ON public.marketplace_products
            FOR EACH ROW
            EXECUTE FUNCTION public.audit_trigger_function();
        
        COMMENT ON TRIGGER audit_marketplace_products_trigger ON public.marketplace_products IS 'Audit trigger for marketplace_products table - logs all create, update, and delete operations';
    END IF;
END $$;

-- === TRIGGERS FOR MARKETPLACE_ORDERS TABLE ===
-- Note: marketplace_orders table may not exist yet
DO $$
BEGIN
    IF EXISTS (
        SELECT 1 FROM information_schema.tables 
        WHERE table_schema = 'public' 
        AND table_name = 'marketplace_orders'
    ) THEN
        DROP TRIGGER IF EXISTS audit_marketplace_orders_trigger ON public.marketplace_orders;
        CREATE TRIGGER audit_marketplace_orders_trigger
            AFTER INSERT OR UPDATE OR DELETE ON public.marketplace_orders
            FOR EACH ROW
            EXECUTE FUNCTION public.audit_trigger_function();
        
        COMMENT ON TRIGGER audit_marketplace_orders_trigger ON public.marketplace_orders IS 'Audit trigger for marketplace_orders table - logs all create, update, and delete operations';
    END IF;
END $$;

-- === TRIGGERS FOR FOLLOWS TABLE ===
DROP TRIGGER IF EXISTS audit_follows_trigger ON public.follows;
CREATE TRIGGER audit_follows_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.follows
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_follows_trigger ON public.follows IS 'Audit trigger for follows table - logs all create, update, and delete operations';

-- === TRIGGERS FOR USER_BLOCKS TABLE ===
DROP TRIGGER IF EXISTS audit_user_blocks_trigger ON public.user_blocks;
CREATE TRIGGER audit_user_blocks_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.user_blocks
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_user_blocks_trigger ON public.user_blocks IS 'Audit trigger for user_blocks table - logs all create, update, and delete operations';

-- === TRIGGERS FOR PLAYLIST_COLLABORATORS TABLE ===
DROP TRIGGER IF EXISTS audit_playlist_collaborators_trigger ON public.playlist_collaborators;
CREATE TRIGGER audit_playlist_collaborators_trigger
    AFTER INSERT OR UPDATE OR DELETE ON public.playlist_collaborators
    FOR EACH ROW
    EXECUTE FUNCTION public.audit_trigger_function();

COMMENT ON TRIGGER audit_playlist_collaborators_trigger ON public.playlist_collaborators IS 'Audit trigger for playlist_collaborators table - logs all create, update, and delete operations';

-- Note: Triggers are set to AFTER to ensure data integrity and allow access to both OLD and NEW records
-- The function captures the full state of records (old and new) in JSONB format for detailed audit trails

