-- ============================================================
-- SOFT DELETE & AUDIT LOG EXTENSION
-- ============================================================
-- Add soft delete columns to core tables
-- ============================================================
ALTER TABLE loads ADD COLUMN deleted_at TIMESTAMPTZ;
ALTER TABLE shippers ADD COLUMN deleted_at TIMESTAMPTZ;
ALTER TABLE vehicles ADD COLUMN deleted_at TIMESTAMPTZ;
ALTER TABLE payments ADD COLUMN deleted_at TIMESTAMPTZ;
ALTER TABLE portal_users ADD COLUMN deleted_at TIMESTAMPTZ;

-- ============================================================
-- AUDIT LOG TABLE
-- ============================================================
CREATE TABLE 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 (if applicable)
    before_json JSONB,                    -- state before change
    after_json JSONB,                     -- state after change
    created_at TIMESTAMPTZ DEFAULT NOW(),
    user_id UUID,                         -- references admin who made change (nullable)
    notes TEXT
);

-- Indexes for fast lookup
CREATE INDEX idx_audit_logs_table ON audit_logs(table_name);
CREATE INDEX idx_audit_logs_user ON audit_logs(user_id);
CREATE INDEX idx_audit_logs_time ON audit_logs(created_at DESC);

-- ============================================================
-- TRIGGERS FOR SOFT DELETE & AUDIT LOGGING
-- ============================================================

-- Function to perform soft delete and log action
CREATE OR REPLACE FUNCTION soft_delete_and_audit()
RETURNS TRIGGER AS $$
DECLARE
    v_user_id UUID;
BEGIN
    -- Determine which table triggered the trigger
    IF TG_TABLE_NAME = 'loads' THEN
        IF OLD.deleted_at IS NOT NULL THEN
            RETURN OLD;  -- already soft-deleted
        END IF;
        UPDATE loads SET deleted_at = NOW() WHERE id = OLD.id;
        IF TG_OP = 'DELETE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, created_at, user_id)
            VALUES ('DELETE', TG_TABLE_NAME, OLD.id::UUID, to_jsonb(OLD), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'UPDATE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, after_json, created_at, user_id)
            VALUES ('UPDATE', TG_TABLE_NAME, NEW.id::UUID, to_jsonb(OLD), to_jsonb(NEW), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'INSERT' THEN
            INSERT INTO audit_logs(action, table_name, row_id, after_json, created_at, user_id)
            VALUES ('INSERT', TG_TABLE_NAME, NEW.id::UUID, NULL, NOW(), current_setting('user_id')::UUID);
        END IF;
    ELSIF TG_TABLE_NAME = 'shippers' THEN
        IF OLD.deleted_at IS NOT NULL THEN
            RETURN OLD;
        END IF;
        UPDATE shippers SET deleted_at = NOW() WHERE id = OLD.id;
        IF TG_OP = 'DELETE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, created_at, user_id)
            VALUES ('DELETE', TG_TABLE_NAME, OLD.id::UUID, to_jsonb(OLD), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'UPDATE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, after_json, created_at, user_id)
            VALUES ('UPDATE', TG_TABLE_NAME, NEW.id::UUID, to_jsonb(OLD), to_jsonb(NEW), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'INSERT' THEN
            INSERT INTO audit_logs(action, table_name, row_id, after_json, created_at, user_id)
            VALUES ('INSERT', TG_TABLE_NAME, NEW.id::UUID, to_jsonb(NEW), NOW(), current_setting('user_id')::UUID);
        END IF;
    ELSIF TG_TABLE_NAME = 'vehicles' THEN
        IF OLD.deleted_at IS NOT NULL THEN
            RETURN OLD;
        END IF;
        UPDATE vehicles SET deleted_at = NOW() WHERE id = OLD.id;
        IF TG_OP = 'DELETE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, created_at, user_id)
            VALUES ('DELETE', TG_TABLE_NAME, OLD.id::UUID, to_jsonb(OLD), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'UPDATE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, after_json, created_at, user_id)
            VALUES ('UPDATE', TG_TABLE_NAME, NEW.id::UUID, to_jsonb(OLD), to_jsonb(NEW), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'INSERT' THEN
            INSERT INTO audit_logs(action, table_name, row_id, after_json, created_at, user_id)
            VALUES ('INSERT', TG_TABLE_NAME, NEW.id::UUID, to_jsonb(NEW), NOW(), current_setting('user_id')::UUID);
        END IF;
    ELSIF TG_TABLE_NAME = 'payments' THEN
        IF OLD.deleted_at IS NOT NULL THEN
            RETURN OLD;
        END IF;
        UPDATE payments SET deleted_at = NOW() WHERE id = OLD.id;
        IF TG_OP = 'DELETE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, created_at, user_id)
            VALUES ('DELETE', TG_TABLE_NAME, OLD.id::UUID, to_jsonb(OLD), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'UPDATE' THEN
            INSERT INTO audit_logs(action, table_name, row_id, before_json, after_json, created_at, user_id)
            VALUES ('UPDATE', TG_TABLE_NAME, NEW.id::UUID, to_jsonb(OLD), to_jsonb(NEW), NOW(), current_setting('user_id')::UUID);
        ELSIF TG_OP = 'INSERT' THEN
            INSERT INTO audit_logs(action, table_name, row_id, after_json, created_at, user_id)
            VALUES ('INSERT', TG_TABLE_NAME, NEW.id::UUID, to_jsonb(NEW), NOW(), current_setting('user_id')::UUID);
        END IF;
    END IF;
    RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;

-- Create triggers for soft delete and audit logging on each table
CREATE TRIGGER trg_loads_soft_delete BEFORE UPDATE OR DELETE ON loads
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();
CREATE TRIGGER trg_loads_soft_delete_INSERT BEFORE INSERT ON loads
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();

CREATE TRIGGER trg_shippers_soft_delete BEFORE UPDATE OR DELETE ON shippers
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();
CREATE TRIGGER trg_shippers_soft_delete_INSERT BEFORE INSERT ON shippers
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();

CREATE TRIGGER trg_vehicles_soft_delete BEFORE UPDATE OR DELETE ON vehicles
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();
CREATE TRIGGER trg_vehicles_soft_delete_INSERT BEFORE INSERT ON vehicles
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();

CREATE TRIGGER trg_payments_soft_delete BEFORE UPDATE OR DELETE ON payments
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();
CREATE TRIGGER trg_payments_soft_delete_INSERT BEFORE INSERT ON payments
    FOR EACH ROW EXECUTE FUNCTION soft_delete_and_audit();

-- ============================================================
-- AUDIT SETUP FUNCTION TO CAPTURE USER ID FROM SESSION CONTEXT
-- ============================================================
-- Note: PostgreSQL cannot directly access Express session, so we pass user_id
-- via SET user_id = '<session_user_id>' before triggering audits.
-- Application must set this variable before performing DB operations.
