require 'rails_helper'

RSpec.describe PostImportRowNormaliser do
  def valid_row(overrides = { })
    {
      sourceRow: '1',
      url: 'https://example.com/post',
      metadataUrl: 'https://example.com/post',
      attributes: { title: 'title', duration: '1' },
      provenance: { url: 'manual', title: 'automatic' },
      tagSources: { automatic: 'tag', manual: '' }
    }.deep_merge(overrides)
  end

  describe '.normalise!' do
    it 'normalises aliases and source rows into a permitted plain hash' do
      row = ActionController::Parameters.new(valid_row)

      expect(described_class.normalise!([row])).to eq([
        {
          'source_row' => 1,
          'url' => 'https://example.com/post',
          'metadata_url' => 'https://example.com/post',
          'attributes' => { 'title' => 'title', 'duration' => '1' },
          'provenance' => { 'url' => 'manual', 'title' => 'automatic' },
          'tag_sources' => { 'automatic' => 'tag', 'manual' => '' }
        }
      ])
    end

    it 'normalises source rows before checking duplicates' do
      rows = [valid_row, valid_row(sourceRow: 1, url: 'https://example.com/other')]

      expect { described_class.normalise!(rows) }
          .to raise_error(ArgumentError, '元行番号が重複しています．')
    end

    it 'rejects non-array batches and non-hash rows' do
      expect { described_class.normalise!({}) }
          .to raise_error(ArgumentError, '取込行の形式が不正です．')
      expect { described_class.normalise!(['row']) }
          .to raise_error(ArgumentError, '取込行の形式が不正です．')
    end

    it 'rejects unknown attributes and invalid field types' do
      expect { described_class.normalise!([valid_row(attributes: { unknown: 'x' })]) }
          .to raise_error(ArgumentError, '取込項目が不正です．')
      expect { described_class.normalise!([valid_row(attributes: { title: [] })]) }
          .to raise_error(ArgumentError, '取込項目の型が不正です．')
      expect { described_class.normalise!([valid_row(attributes: { duration: false })]) }
          .to raise_error(ArgumentError, '取込項目の型が不正です．')
    end

    it 'rejects unknown provenance and tag-source values' do
      expect { described_class.normalise!([valid_row(provenance: { title: 'mapped' })]) }
          .to raise_error(ArgumentError, '値の由来が不正です．')
      expect { described_class.normalise!([valid_row(tagSources: { mapped: 'tag' })]) }
          .to raise_error(ArgumentError, 'タグ由来の形式が不正です．')
    end

    it 'accepts warning fields only at the validation boundary' do
      row = valid_row.merge(
        fieldWarnings: { title: ['取得できませんでした．'] },
        baseWarnings: ['確認してください．']
      )

      without_warnings = described_class.normalise!([row]).first
      with_warnings = described_class.normalise!([row], allow_warning_fields: true).first

      expect(without_warnings).not_to include('field_warnings', 'base_warnings')
      expect(with_warnings).to include(
        'field_warnings' => { 'title' => ['取得できませんでした．'] },
        'base_warnings' => ['確認してください．']
      )
    end
  end
end
