class CreateWikiVersions < ActiveRecord::Migration[8.0]
  class WikiPage < ActiveRecord::Base
    self.table_name = 'wiki_pages'
  end

  class WikiRevision < ActiveRecord::Base
    self.table_name = 'wiki_revisions'
  end

  class WikiRevisionLine < ActiveRecord::Base
    self.table_name = 'wiki_revision_lines'
  end

  class WikiLine < ActiveRecord::Base
    self.table_name = 'wiki_lines'
  end

  class WikiVersion < ActiveRecord::Base
    self.table_name = 'wiki_versions'
  end

  class TagName < ActiveRecord::Base
    self.table_name = 'tag_names'
  end

  def up
    add_column :wiki_pages, :body, :text, after: :tag_name_id

    create_table :wiki_versions do |t|
      t.references :wiki_page, null: false, foreign_key: true
      t.integer :version_no, null: false
      t.string :event_type, null: false
      t.string :title, null: false
      t.text :body, null: false
      t.text :reason
      t.datetime :created_at, null: false
      t.references :created_by_user, foreign_key: { to_table: :users }

      t.index [:wiki_page_id, :version_no], unique: true
      t.check_constraint 'version_no > 0',
                         name: 'wiki_versions_version_no_positive'
      t.check_constraint "event_type IN ('create', 'update', 'discard', 'restore')",
                         name: 'wiki_versions_event_type_valid'
    end

    WikiPage.reset_column_information
    WikiVersion.reset_column_information

    say_with_time 'Backfilling wiki_versions' do
      WikiPage.find_each do |page|
        base_revision_id = nil
        version_no = 1
        title = TagName.find(page.tag_name_id).name
        body = nil
        loop do
          rev = WikiRevision.where(wiki_page_id: page.id).find_by(base_revision_id:)
          break unless rev

          body = WikiRevisionLine.where(wiki_revision_id: rev.id).order(:position).map { |wrl|
            WikiLine.find(wrl.wiki_line_id).body
          }.join("\n")

          WikiVersion.create!(
              wiki_page_id: page.id,
              version_no:,
              event_type: version_no == 1 ? 'create' : 'update',
              title:,
              body:,
              reason: rev.message,
              created_at: rev.created_at,
              created_by_user_id: rev.created_user_id)

          version_no += 1
          base_revision_id = rev.id
        end
        if body
          page.update!(body:)
        else
          page.destroy!
        end
      end
    end

    change_column_null :wiki_pages, :body, false
  end

  def down
    drop_table :wiki_versions
    remove_column :wiki_pages, :body
  end
end
