# frozen_string_literal: true

module Migration
  class BaseDropper
    FUNCTION_SCHEMA_NAME ||= "discourse_functions"

    def self.create_readonly_function(table_name, column_name = nil)
      DB.exec <<~SQL
        CREATE SCHEMA IF NOT EXISTS #{FUNCTION_SCHEMA_NAME};
      SQL

      message =
        (
          if column_name
            "Discourse: #{column_name} in #{table_name} is readonly"
          else
            "Discourse: #{table_name} is read only"
          end
        )

      DB.exec <<~SQL
        CREATE OR REPLACE FUNCTION #{readonly_function_name(table_name, column_name)} RETURNS trigger AS $rcr$
          BEGIN
            RAISE EXCEPTION '#{message}';
          END
        $rcr$ LANGUAGE plpgsql;
      SQL
    end

    def self.drop_readonly_function(table_name, column_name = nil)
      DB.exec("DROP FUNCTION IF EXISTS #{readonly_function_name(table_name, column_name)} CASCADE")
    end

    def self.readonly_function_name(table_name, column_name = nil, with_schema: true)
      function_name = ["raise", table_name, column_name, "readonly()"].compact.join("_")

      if with_schema && function_schema_exists?
        "#{FUNCTION_SCHEMA_NAME}.#{function_name}"
      else
        function_name
      end
    end

    def self.old_readonly_function_name(table_name, column_name = nil)
      readonly_function_name(table_name, column_name).sub("#{FUNCTION_SCHEMA_NAME}.", "")
    end

    def self.readonly_trigger_name(table_name, column_name = nil)
      [table_name, column_name, "readonly"].compact.join("_")
    end

    def self.function_schema_exists?
      DB.exec(<<~SQL).to_s == "1"
        SELECT schema_name
        FROM information_schema.schemata
        WHERE schema_name = '#{FUNCTION_SCHEMA_NAME}'
      SQL
    end

    def self.existing_discourse_function_names
      DB.query_single(<<~SQL)
        SELECT routine_name::text
        FROM information_schema.routines
        WHERE routine_type = 'FUNCTION' AND specific_schema = '#{FUNCTION_SCHEMA_NAME}'
      SQL
    end
  end
end