# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Api::SyncController, type: :controller do
  let(:current_user) { create(:user, :admin) }

  before do
    sign_in_to_api(current_user)
  end

  describe '#index' do
    it 'dumps all the data when parameter since not suplied' do
      create_default_data

      get :index

      expect(response).to be_successful
    end

    it 'does not leak data from other accounts' do
      another_user = create(:user)
      my_project = create(:project, account: current_user.primary_account)
      their_project = create(:project, account: another_user.primary_account)
      my_contract_template = create(:contract_template, project: my_project)
      their_contract_template = create(:contract_template, project: their_project)
      my_appearance_release = create(:appearance_release, project: my_project)
      their_appearance_release = create(:appearance_release, project: their_project)
      my_talent_release = create(:talent_release, project: my_project)
      their_talent_release = create(:talent_release, project: their_project)
      my_location_release = create(:location_release, project: my_project)
      their_location_release = create(:location_release, project: their_project)
      my_material_release = create(:material_release, project: my_project)
      their_material_release = create(:material_release, project: their_project)
      my_note = create(:note, notable: my_appearance_release, user: current_user)
      their_note = create(:note, notable: their_appearance_release, user: another_user)

      get :index

      account_ids = ids_for_type('accounts')
      project_ids = ids_for_type('projects')
      contract_template_ids = ids_for_type('contract_templates')
      appearance_release_ids = ids_for_type('appearance_releases')
      talent_release_ids = ids_for_type('talent_releases')
      location_release_ids = ids_for_type('location_releases')
      material_release_ids = ids_for_type('material_releases')
      note_ids = ids_for_type('notes')

      expect(account_ids).to include(current_user.primary_account.id.to_s)
      expect(account_ids).not_to include(another_user.primary_account.id.to_s)
      expect(project_ids).to include(my_project.id.to_s)
      expect(project_ids).not_to include(their_project.id.to_s)
      expect(contract_template_ids).to include(my_contract_template.id.to_s)
      expect(contract_template_ids).not_to include(their_contract_template.id.to_s)
      expect(appearance_release_ids).to include(my_appearance_release.id.to_s)
      expect(appearance_release_ids).not_to include(their_appearance_release.id.to_s)
      expect(location_release_ids).to include(my_location_release.id.to_s)
      expect(location_release_ids).not_to include(their_location_release.id.to_s)
      expect(talent_release_ids).to include(my_talent_release.id.to_s)
      expect(talent_release_ids).not_to include(their_talent_release.id.to_s)
      expect(material_release_ids).to include(my_material_release.id.to_s)
      expect(material_release_ids).not_to include(their_material_release.id.to_s)
      expect(note_ids).to include(my_note.id.to_s)
      expect(note_ids).not_to include(their_note.id.to_s)
    end

    it 'returns only the notes that belong to the accessible projects (the note bug)' do
      create_default_data

      my_appearance_release = AppearanceRelease.last
      my_note = create(:note, notable: my_appearance_release, user: current_user)
      another_user = create(:user)
      their_project = create(:project, account: another_user.primary_account)
      their_appearance_release = create(:appearance_release, project: their_project)
      their_note = create(:note, notable: their_appearance_release, user: another_user)
      another_user.account_auths.create(account: current_user.primary_account, role: :account_manager)

      get :index

      note_ids = ids_for_type('notes')
      expect(note_ids).to eq [my_note.id.to_s]
    end

    it 'shows guardian_photo property for appearance and talent releases and not for other release types' do
      create_default_data

      get :index

      appearance_releases = attributes_for_type('appearance_releases')
      talent_releases = attributes_for_type('talent_releases')
      location_releases = attributes_for_type('location_releases')
      material_releases = attributes_for_type('material_releases')

      expect(appearance_releases.first).to include('guardian_photo')
      expect(talent_releases.first).to include('guardian_photo')
      expect(location_releases.first).not_to include('guardian_photo')
      expect(material_releases.first).not_to include('guardian_photo')
    end

    it 'guardian photo has same format as other photos' do
      create_default_data_with_guardian_info

      get :index

      appearance_releases = attributes_for_type('appearance_releases')
      guardian_photo = appearance_releases.first['guardian_photo']
      photo_attributes = guardian_photo['attributes']

      expect(appearance_releases.first).to include('guardian_photo')
      expect(guardian_photo).to include('id', 'type', 'attributes')
      expect(photo_attributes).to include('filename', 'content_type', 'url', 'thumbnail_url')
    end
  end

  private

  def create_default_data
    project = create(:project, name: 'first', account: current_user.primary_account)
    create(:appearance_release, project: project)
    create(:talent_release, project: project)
    create(:location_release, project: project)
    create(:material_release, project: project)
  end

  def create_default_data_with_guardian_info
    project = create(:project, name: 'first', account: current_user.primary_account)
    create(:appearance_release, :minor_with_guardian_photo, project: project)
  end

  def response_body_json
    JSON.parse(response.body)
  end

  def ids_for_type(name)
    response_body_json.dig('data', name).flat_map { |json| json.dig('attributes', 'id') }
  end

  def attributes_for_type(name)
    response_body_json.dig('data', name).flat_map { |json| json['attributes'] }
  end
end
