# frozen_string_literal: true

require "migration/base_dropper"

module Migration
  class ColumnDropper
    def self.mark_readonly(table_name, column_name)
      has_default = DB.query_single(<<~SQL, table_name: table_name, column_name: column_name).first
        SELECT column_default IS NOT NULL
        FROM information_schema.columns
        WHERE table_name = :table_name
        AND column_name = :column_name
      SQL

      raise "You must drop a column's default value before marking it as readonly" if has_default

      BaseDropper.create_readonly_function(table_name, column_name)

      DB.exec <<~SQL
        CREATE TRIGGER #{BaseDropper.readonly_trigger_name(table_name, column_name)}
        BEFORE INSERT OR UPDATE OF #{column_name}
        ON #{table_name}
        FOR EACH ROW
        WHEN (NEW.#{column_name} IS NOT NULL)
        EXECUTE PROCEDURE #{BaseDropper.readonly_function_name(table_name, column_name)};
      SQL
    end

    def self.execute_drop(table, columns)
      table = table.to_s

      columns.each do |column|
        column = column.to_s
        self.drop_readonly(table, column)
        # safe cause it is protected on method entry, can not be passed in params
        DB.exec("ALTER TABLE #{table} DROP COLUMN IF EXISTS #{column}")
      end
    end

    def self.drop_readonly(table_name, column_name)
      BaseDropper.drop_readonly_function(table_name, column_name)

      # Backward compatibility for old functions created in the public schema
      DB.exec(
        "DROP FUNCTION IF EXISTS #{BaseDropper.old_readonly_function_name(table_name, column_name)} CASCADE",
      )
    end
  end
end