require 'rails_helper'

RSpec.describe Wiki::Commit do
  let(:user) { create_member_user! }

  def create_page(title: 'commit_spec_page', body: 'initial body')
    tag_name = TagName.create!(name: title)

    Wiki::Commit.create_content!(
        tag_name:,
        body:,
        created_by_user: user,
        message: 'init')
  end

  describe '.content!' do
    it 'stores normalised body in wiki_pages and wiki_versions' do
      page = create_page(title: 'commit_normalised_page')

      described_class.content!(
        page:,
        body: "a\r\nb\r\n\r\n",
        created_user: user,
        message: 'init'
      )

      page.reload
      version = page.wiki_versions.order(:version_no).last

      expect(page.body).to eq("a\nb")
      expect(version.body).to eq("a\nb")
      expect(page.current_revision.lines_count).to eq(2)
    end

    it 'deduplicates duplicated missing wiki lines before upsert' do
      page = create_page(title: 'commit_duplicate_line_page')
      duplicated = 'commit_duplicate_line'

      described_class.content!(
        page:,
        body: "#{ duplicated }\n#{ duplicated }",
        created_user: user,
        message: 'init'
      )

      page.reload

      expect(WikiLine.where(body: duplicated).count).to eq(1)
      expect(page.current_revision.lines_count).to eq(2)
      expect(page.current_revision.wiki_revision_lines.count).to eq(2)
    end

    it 'raises conflict when base_revision_id is stale' do
      page = create_page(title: 'commit_conflict_page')

      first = described_class.content!(
        page:,
        body: 'first',
        created_user: user,
        message: 'first'
      )

      described_class.content!(
        page:,
        body: 'second',
        created_user: user,
        message: 'second',
        base_revision_id: first.id
      )

      expect {
        described_class.content!(
          page:,
          body: 'third',
          created_user: user,
          message: 'third',
          base_revision_id: first.id
        )
      }.to raise_error(Wiki::Commit::Conflict)
    end

    it 'does not record tag version when corresponding tag has no versions' do
      tag_name = TagName.create!(name: 'commit_linked_tag_without_versions')
      tag = Tag.create!(tag_name:, category: :general)

      page =
          described_class.create_content!(
              tag_name:,
              body: 'before',
              created_by_user: user,
              message: 'init')

      expect(tag.reload.tag_versions.count).to eq(0)

      current_revision_id = page.current_revision.id

      expect {
        described_class.content!(
            page:,
            body: 'after',
            created_user: user,
            message: 'edit',
            base_revision_id: current_revision_id)
      }.to change(WikiVersion, :count).by(1)

      expect(tag.reload.tag_versions.count).to eq(0)
    end

    it 'does not record tag version when corresponding tag has no versions' do
      tag_name = TagName.create!(name: 'commit_linked_tag_without_versions')
      tag = Tag.create!(tag_name:, category: :general)

      page =
          described_class.create_content!(
              tag_name:,
              body: 'before',
              created_by_user: user,
              message: 'init')

      current_revision_id = page.current_revision.id

      expect {
        described_class.content!(
            page:,
            body: 'after',
            created_user: user,
            message: 'edit',
            base_revision_id: current_revision_id)
      }.to change(WikiVersion, :count).by(1)

      expect(tag.reload.tag_versions.count).to eq(0)
    end
  end

  describe '.redirect!' do
    it 'raises because redirect revisions are deprecated' do
      page = create_page(title: 'commit_redirect_source')
      target = create_page(title: 'commit_redirect_target')

      expect {
        described_class.redirect!(
          page:,
          redirect_page: target,
          created_user: user,
          message: 'redirect'
        )
      }.to raise_error(RuntimeError, '廃止しました．')
    end
  end
end
