-- ============================================================
-- FreightDesk — Migration 004: Audit Logging
-- Adapted from Hermes agent's soft-delete-audit branch
-- Adds audit_logs table + triggers for core tables
-- ============================================================

-- ============================================================
-- AUDIT LOG TABLE
-- ============================================================
CREATE TABLE IF NOT EXISTS audit_logs (
    id BIGSERIAL PRIMARY KEY,
    action TEXT NOT NULL,                 -- 'INSERT', 'UPDATE', 'DELETE'
    table_name TEXT NOT NULL,             -- e.g., 'loads', 'shippers'
    row_id UUID,                          -- UUID of the affected row
    before_json JSONB,                    -- state before change
    after_json JSONB,                     -- state after change
    created_at TIMESTAMPTZ DEFAULT NOW(),
    user_id UUID,                         -- admin who made change (nullable)
    notes TEXT
);

-- Indexes for fast lookup
CREATE INDEX IF NOT EXISTS idx_audit_logs_table ON audit_logs(table_name);
CREATE INDEX IF NOT EXISTS idx_audit_logs_user ON audit_logs(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_logs_time ON audit_logs(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_audit_logs_row ON audit_logs(table_name, row_id);

-- ============================================================
-- AUDIT TRIGGER FUNCTION
-- Captures INSERT, UPDATE, DELETE on core tables
-- Uses PostgreSQL session variable app.current_user_id for user tracking
-- ============================================================
CREATE OR REPLACE FUNCTION fn_audit_trigger()
RETURNS TRIGGER AS $$
DECLARE
    v_user_id UUID;
BEGIN
    -- Get user_id from session variable (set by app before DB ops)
    BEGIN
        v_user_id := current_setting('app.current_user_id', true)::UUID;
    EXCEPTION WHEN OTHERS THEN
        v_user_id := NULL;
    END;

    IF TG_OP = 'INSERT' THEN
        INSERT INTO audit_logs(action, table_name, row_id, after_json, user_id)
        VALUES ('INSERT', TG_TABLE_NAME, NEW.id, to_jsonb(NEW), v_user_id);
        RETURN NEW;

    ELSIF TG_OP = 'UPDATE' THEN
        -- Skip if only deleted_at changed (soft-delete is logged separately)
        IF OLD.deleted_at IS NULL AND NEW.deleted_at IS NOT NULL THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, after_json, user_id, notes)
            VALUES ('SOFT_DELETE', TG_TABLE_NAME, OLD.id, to_jsonb(OLD), to_jsonb(NEW), v_user_id, 'Soft delete via trigger');
        ELSE
            INSERT INTO audit_logs(action, table_name, row_id, before_json, after_json, user_id)
            VALUES ('UPDATE', TG_TABLE_NAME, NEW.id, to_jsonb(OLD), to_jsonb(NEW), v_user_id);
        END IF;
        RETURN NEW;

    ELSIF TG_OP = 'DELETE' THEN
        INSERT INTO audit_logs(action, table_name, row_id, before_json, user_id, notes)
        VALUES ('HARD_DELETE', TG_TABLE_NAME, OLD.id, to_jsonb(OLD), v_user_id, 'Hard delete (bypasses soft-delete)');
        RETURN OLD;
    END IF;

    RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- ============================================================
-- ATTACH TRIGGERS TO CORE TABLES
-- ============================================================
DROP TRIGGER IF EXISTS trg_audit_loads ON loads;
CREATE TRIGGER trg_audit_loads
    AFTER INSERT OR UPDATE OR DELETE ON loads
    FOR EACH ROW EXECUTE FUNCTION fn_audit_trigger();

DROP TRIGGER IF EXISTS trg_audit_shippers ON shippers;
CREATE TRIGGER trg_audit_shippers
    AFTER INSERT OR UPDATE OR DELETE ON shippers
    FOR EACH ROW EXECUTE FUNCTION fn_audit_trigger();

DROP TRIGGER IF EXISTS trg_audit_vehicles ON vehicles;
CREATE TRIGGER trg_audit_vehicles
    AFTER INSERT OR UPDATE OR DELETE ON vehicles
    FOR EACH ROW EXECUTE FUNCTION fn_audit_trigger();

DROP TRIGGER IF EXISTS trg_audit_payments ON payments;
CREATE TRIGGER trg_audit_payments
    AFTER INSERT OR UPDATE OR DELETE ON payments
    FOR EACH ROW EXECUTE FUNCTION fn_audit_trigger();

DROP TRIGGER IF EXISTS trg_audit_portal_users ON portal_users;
CREATE TRIGGER trg_audit_portal_users
    AFTER INSERT OR UPDATE OR DELETE ON portal_users
    FOR EACH ROW EXECUTE FUNCTION fn_audit_trigger();

-- ============================================================
-- HELPER: Function to set current user for audit context
-- Call this from Express middleware before DB operations:
--   await supabase.rpc('set_audit_user', { user_id: req.session.user.id })
-- ============================================================
CREATE OR REPLACE FUNCTION set_audit_user(user_id UUID)
RETURNS VOID AS $$
BEGIN
    PERFORM set_config('app.current_user_id', user_id::TEXT, false);
END;
$$ LANGUAGE plpgsql;
