require "rails_helper"

releases = [
  {
    type: :appearance_release,
    obligatory_attribute: :person_name
  },
  {
    type: :talent_release,
    obligatory_attribute: :person_name
  },
  {
    type: :location_release,
    obligatory_attribute: :name
  },
  {
    type: :material_release,
    obligatory_attribute: :name
  }
]

describe "IOS App Support API" do
  let(:current_user) { create(:user, :manager) }
  let!(:project) { create(:project, name: "project one", members: current_user, account: current_user.primary_account) }
  let!(:template) { create(:contract_template, name: "cote1", project: project) }

  it 'lists projects' do
    get '/api/v1/projects', headers: required_headers(current_user)

    json = JSON.parse(response.body)

    expect(response.status).to eq 200
    expect(json["data"].length).to eq 1
  end

  it 'lists broadcasts' do
    allow(MuxLiveStream).to receive(:new).and_return(double(id: "id", key: "key", playback_id: "playback_id"))

    br1 = create(:broadcast, project: project, name: "Created Bc", status: "created")
    br2 = create(:broadcast, project: project, name: "Idle Bc", status: "idle")

    get "/api/v1/projects/#{project.id}/broadcasts", headers: required_headers(current_user)

    json = JSON.parse(response.body)

    expect(response.status).to eq 200
    expect(json["data"].length).to eq 2
  end

  it 'lists contract templates' do
    get "/api/v1/projects/#{project.id}/contract_templates", headers: required_headers(current_user)

    json = JSON.parse(response.body)

    expect(response.status).to eq 200
    expect(json["data"].length).to eq 1
  end

  it 'shows details of contract templates' do
    get "/api/v1/contract_templates/#{template.id}", headers: required_headers(current_user)

    json = JSON.parse(response.body)

    expect(response.status).to eq 200
    expect(json["data"]["attributes"].keys.length).to be > 1
    expect(response.body).to match /cote1/
  end

  it 'lists releases' do
    releases.each do |release|
      r = create(release[:type], release[:obligatory_attribute] => "ct1", :project_id => project.id)

      get "/api/v1/projects/#{project.id}/#{release[:type].to_s.pluralize}", headers: required_headers(current_user)

      json = JSON.parse(response.body)

      expect(response.status).to eq 200
      expect(json["data"].length).to eq 1
      expect(json["data"].first['attributes'][release[:obligatory_attribute].to_s]).to eq r.public_send release[:obligatory_attribute]
    end
  end

  it 'shows details of releases' do
    releases.each do |release|
      r = create(release[:type], release[:obligatory_attribute] => "ct1", :project_id => project.id)

      get "/api/v1/#{release[:type].to_s.pluralize}/#{r.id}", headers: required_headers(current_user)

      json = JSON.parse(response.body)

      expect(response.status).to eq 200
      expect(json["data"]["attributes"].keys.length).to be > 1
      expect(response.body).to match /ct1/
    end
  end

  it 'lists notes' do
    releases.each do |release|
      r = create(release[:type], release[:obligatory_attribute] => "ct1", :project_id => project.id)
      n = create(:note, :notable => r, :content => "Simple Note", :user => current_user, :email => current_user.email)
      get "/api/v1/#{release[:type].to_s.pluralize}/#{r.id}/notes", headers: required_headers(current_user)

      json = JSON.parse(response.body)

      expect(json["data"].length).to eq 1
      expect(response.body).to match /#{n.content}/
      expect(response.body).to match /#{current_user.email}/
    end
  end

  it 'creates notes' do
    releases.each do |release|
      r = create(release[:type], release[:obligatory_attribute] => "ct1", :project_id => project.id)

      note = { "data" => { "type" => "note", "attributes" => { "content" => "This is a note!" } } }

      post "/api/v1/#{release[:type].to_s.pluralize}/#{r.id}/notes", params: note.to_json, headers: required_headers(current_user)

      json = JSON.parse(response.body)

      expect(json["data"]["attributes"].keys.length).to be > 1
      expect(response.body).to match /This is a note!/
    end
  end

  it 'creates appearance release' do
    allow(BrayniacAI::Validation).to receive(:create).and_return(double(:validation, valid: true))
    release = releases.first
    release_json = { "data" => {
      "type" => "appearance_release",
      "attributes" => {
        "person_first_name" => "Real",
        "person_last_name" => "Person",
        "person_photo" => {
          "io" => "#{photo_base64}",
          "filename" => "adano.jpg",
        },
        "signature" => "#{signature_base64}",
        "person_phone" => "123"
      }
    } }.to_json

    post "/api/v1/contract_templates/#{template.id}/#{release[:type].to_s.pluralize}", params: release_json, headers: required_headers(current_user)

    json = JSON.parse(response.body)

    expect(response.status).to eq 201
    expect(json["data"]["attributes"].keys.length).to be > 1
    expect(response.body).to match /Real/
    expect(response.body).to match /Person/
  end

  it 'creates talent, material and location releases' do
    releases.each do |release|
      next if release[:type] == :appearance_release

      release_json = { "data" => {
        "type" => release[:type].to_s,
        "attributes" => {
          release[:obligatory_attribute] => "Real Release",
          "person_first_name" => "Real",
          "person_last_name" => "Release",
          "photos" => [
            { "io" => "#{photo_base64}", "filename" => "adano.jpg" }
          ],
          "signature" => "#{signature_base64}",
          "person_phone" => "123"
        }
      } }.to_json
      post "/api/v1/contract_templates/#{template.id}/#{release[:type].to_s.pluralize}", params: release_json, headers: required_headers(current_user)

      json = JSON.parse(response.body)
      expect(json["data"]["attributes"].keys.length).to be > 1
      expect(response.body).to match /Real/
      expect(response.body).to match /Release/
    end
  end

  it 'adds photos to talent, material and location releases' do
    releases.each do |release|
      next if release[:type] == :appearance_release

      r = create(release[:type], release[:obligatory_attribute] => "ct1", :project_id => project.id)
      old_photo_count = r.photos.length

      photos_json = { "data" => {
        "type" => release[:type].to_s,
        "attributes" => {
          "photos" => [
            { "io" => "#{photo_base64}", "filename" => "adano.jpg" }
          ]
        }
      } }.to_json

      put "/api/v1/#{release[:type].to_s.pluralize}/#{r.id}", params: photos_json, headers: required_headers(current_user)
      json = JSON.parse(response.body)
      r.reload
      expect(json["data"]["attributes"].keys.length).to be > 1
      expect(response.body).to match /ct1/
      expect(r.photos.length).to eq old_photo_count + 1
    end
  end

  private

  def required_headers(user)
    token = Knock::AuthToken.new(payload: { sub: user.id }).token
    {
      'Authorization': "Bearer #{token}",
      'Content-type': "application/vnd.api+json"
    }
  end

  def photo_base64
    @photo_base64 ||= Base64Image.from_image(file_fixture("person_photo.png")).data_uri
  end

  def signature_base64
    @signature_base64 ||= Base64Image.from_image(file_fixture("signature.png")).data_uri
  end
end
