# frozen_string_literal: true

require 'rails_helper'

describe ContractTemplatesController do
  render_views

  let(:current_user) { create(:user, :manager) }
  let(:project) { create(:project, members: current_user, account: current_user.primary_account) }

  before do
    sign_in(current_user)
  end

  describe '#index' do
    it 'responds successfully' do
      get :index, params: { project_id: project }

      expect(response).to be_successful
    end

    it 'renders content' do
      contract_template = create(:contract_template,
                                 name: 'My Contract Template', fee: 50, release_type: 'appearance',
                                 project: project)
      sign_path = new_account_project_contract_template_appearance_release_path(project.account, project, contract_template)
      sign_url = new_account_project_contract_template_appearance_release_url(project.account, project, contract_template)

      get :index, params: { project_id: project }

      expect(response.body).to have_content('My Contract Template')
      expect(response.body).to have_link('Create New Release Template', href: new_project_contract_template_path(project))
      expect(response.body).to have_link('Import Release Template', href: new_project_release_template_imports_path(project))
      expect(response.body).to have_link('Copy Release URL', href: sign_url)
      expect(response.body).to have_content('Manage')
      expect(response.body).to have_link('Sign', href: sign_path)
      expect(response.body).to have_link('Print')

    end

    context 'when there are no contract templates' do
      it 'renders an empty message' do
        get :index, params: { project_id: project }

        expect(response.body).to have_content('Release Templates will appear here')
      end
    end

    context 'when current user is an associate' do
      let(:current_user) { create(:user, :associate) }

      it 'does not show the new contract template button' do
        get :index, params: { project_id: project }

        expect(response.body).not_to have_link('Create New Release Template')
        expect(response.body).not_to have_link('Import Release Template')
        expect(response.body).not_to have_link('Delete')
      end
    end

    context 'when there are many records' do
      it 'paginates the table' do
        create_list(:contract_template, 20, project: project)

        get :index, params: { project_id: project }

        expect(response.body).to have_link('2', href: project_contract_templates_path(project, page: 2))
      end
    end
  end

  describe '#new' do
    it 'responds ok' do
      get :new, params: { project_id: project }

      expect(response).to be_successful
    end
  end

  describe '#create' do
    it 'redirects' do
      post :create, params: { project_id: project, contract_template: contract_template_params(valid: true) }

      expect(response).to redirect_to(project_contract_templates_path(project))
    end

    it 'sends pdf file for a preview' do
      post :create, params: { project_id: project, contract_template: contract_template_params(valid: true), commit: 'preview' }

      expect(response.header['Content-Type']).to include('application/pdf')
      expect(response.header['Content-Disposition']).to include('inline')
    end

    it 'creates a new record' do
      expect do
        post :create, params: { project_id: project, contract_template: contract_template_params }
      end.to change(ContractTemplate, :count).by(1)
    end

    context 'when save fails' do
      it 'responds ok' do
        post :create, params: { project_id: project, contract_template: contract_template_params(valid: false) }

        expect(response).to be_successful
      end
    end

    context 'when current user is an associate' do
      let(:current_user) { create(:user, :associate) }

      it 'raises exception' do
        expect do
          post :create, params: { project_id: project, contract_template: contract_template_params }
        end.to raise_error(Pundit::NotAuthorizedError)
      end
    end
  end

  describe '#destroy' do
    let!(:contract_template) { create(:contract_template, project: project) }

    it 'redirects' do
      delete :destroy, params: { id: contract_template }

      expect(response).to be_redirect
      expect(response).to redirect_to [project, :contract_templates]
    end

    it 'archives the record but does not delete' do
      expect do
        delete :destroy, params: { id: contract_template }
      end.to change(ContractTemplate, :count).by(0)
      expect(ContractTemplate.find(contract_template.id).archived_at).not_to be_nil
    end

    context 'when contract template has associated releases' do
      let(:contract_template) { create(:contract_template, appearance_releases: build_list(:appearance_release, 1), project: project) }

      it 'does not raise error' do
        expect do
          delete :destroy, params: { id: contract_template }
        end.not_to raise_error
      end
    end
  end

  private

  def contract_template_params(valid: true)
    if valid
      attributes_for(:contract_template).merge(exploitable_rights_params)
    else
      attributes_for(:contract_template).except(:name)
    end
  end

  def exploitable_rights_params
    {
      applicable_medium_id: ApplicableMedium.last.id,
      applicable_medium_text: 'applicable_media',
      territory_id: Territory.last.id,
      territory_text: 'territory',
      term_id: Term.last.id,
      term_text: 'term',
      restriction_id: Restriction.last.id,
      restriction_text: 'restrictions'
    }
  end
end
