require 'rails_helper'

RSpec.describe MaterialSyncRunner do
  let(:user) { create(:user, :member) }
  let(:source) do
    MaterialSyncSource.create!(
        name: 'Drive source',
        source_kind: 'google_drive_path',
        source_file_id: 'folder-123',
        profile: 'legacy_drive',
        created_by_user: user,
        updated_by_user: user)
  end
  let(:drive_client) { instance_double(GoogleDrive::ApiClient) }

  describe '#sync!' do
    it 'imports google drive path candidates as they are yielded' do
      first_entry = { id: 'file-1',
                      name: 'a.png',
                      mime_type: 'image/png',
                      relative_path: '素材/a.png',
                      sha256_checksum: 'sha-a',
                      web_view_link: 'https://drive.google.com/file/d/file-1/view',
                      web_content_link: nil }
      second_entry = { id: 'file-2',
                       name: 'b.png',
                       mime_type: 'image/png',
                       relative_path: '素材/b.png',
                       sha256_checksum: 'sha-b',
                       web_view_link: 'https://drive.google.com/file/d/file-2/view',
                       web_content_link: nil }
      yielded = []

      allow(GoogleDrive::ApiClient).to receive(:new).and_return(drive_client)
      allow(drive_client).to receive(:each_material_file_under_folder) do |folder_id, &block|
        expect(folder_id).to eq('folder-123')
        block.call(first_entry)
        expect(yielded).to eq(['素材/a.png'])
        block.call(second_entry)
      end
      allow(MaterialSyncImporter).to receive(:import!) do |candidate|
        yielded << candidate.fetch(:source_path)
        instance_double(MaterialSyncImporter::Result,
                        action: yielded.last == '素材/a.png' ? :imported : :updated)
      end

      result = described_class.new(source).sync!

      expect(yielded).to eq(['素材/a.png', '素材/b.png'])
      expect(result.imported).to eq(1)
      expect(result.updated).to eq(1)
      expect(result.unchanged).to eq(0)
      expect(source.reload.last_synced_at).to be_present
    end

    it 'logs google drive path progress at first item and summary' do
      entry = { id: 'file-1',
                name: 'a.png',
                mime_type: 'image/png',
                relative_path: '素材/a.png',
                sha256_checksum: 'sha-a',
                web_view_link: 'https://drive.google.com/file/d/file-1/view',
                web_content_link: nil }
      logged = []

      allow(GoogleDrive::ApiClient).to receive(:new).and_return(drive_client)
      allow(drive_client).to receive(:each_material_file_under_folder) do |_folder_id, &block|
        block.call(entry)
      end
      allow(MaterialSyncImporter).to receive(:import!)
        .and_return(instance_double(MaterialSyncImporter::Result, action: :imported))
      allow(Rails.logger).to receive(:info) { |message| logged << JSON.parse(message) }

      described_class.new(source).sync!

      progress_logs = logged.select { |row| row['folder_id'] == 'folder-123' }
      expect(progress_logs.map { |row| row['progress'] }).to eq(['scan', 'summary'])
      expect(progress_logs.last).to include(
          'material_sync_source_id' => source.id,
          'material_sync_source_name' => 'Drive source',
          'scanned_count' => 1,
          'imported' => 1,
          'updated' => 0,
          'unchanged' => 0,
          'suppressed' => 0,
          'failed' => 0)
    end
  end
end
