require 'spec_helper'
require 'webmock/rspec'

describe "User Subscriptions" do

  let(:user1) {FactoryGirl.create(:user)}
  let(:client) { RecurlyClient.new }

  it "empty results" do
    user1.touch

    User.subscription_sync

    user1.reload

    user1.subscription_sync_code.should == 'no_recurly_account'
    user1.subscription_last_checked_at.should_not be_nil
  end

  it "user not in trial" do
    user1.subscription_plan_code = SubscriptionDefinitions::JAM_PLATINUM
    user1.subscription_trial_ends_at = 1.days.ago

    client.sync_subscription(user1)
    user1.reload
    user1.subscription_sync_code.should == "trial_ended"
    user1.subscription_last_checked_at.should_not be_nil
    user1.subscription_plan_code.should be_nil

    user1.subscription_trial_ends_at = 3.days.ago
    user1.subscription_last_checked_at = 2.days.ago
    user1.save!

    User.subscription_sync

    user1.reload

    user1.subscription_sync_code.should == "trial_ended"
    user1.subscription_last_checked_at.should_not be_nil
    user1.subscription_plan_code.should be_nil
  end

  it "revert admin user down" do
    user1.subscription_plan_code = SubscriptionDefinitions::JAM_PLATINUM
    user1.subscription_trial_ends_at = 1.days.ago
    user1.admin_override_plan_code = SubscriptionDefinitions::JAM_PLATINUM
    user1.admin_override_ends_at = 10.days.from_now
    user1.save!

    User.subscription_sync

    user1.reload

    user1.subscription_sync_code.should == "admin_control"
    user1.subscription_last_checked_at.should_not be_nil
    user1.subscription_plan_code.should == SubscriptionDefinitions::JAM_PLATINUM

    user1.subscription_trial_ends_at = 3.days.ago
    user1.admin_override_ends_at = 10.days.ago
    user1.subscription_last_checked_at = 2.days.ago
    user1.save!

    User.subscription_sync
    user1.reload

    user1.subscription_sync_code.should == "trial_ended"
    user1.subscription_last_checked_at.should_not be_nil
    user1.subscription_plan_code.should be_nil

  end

end

describe 'Subscription transactions sync' do
  let(:client) { RecurlyClient.new }
  let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) }
  let(:user) { FactoryGirl.create(:user, affiliate_referral: affiliate_partner) }
  let(:user2) { FactoryGirl.create(:user, affiliate_referral: affiliate_partner) }
  let(:transaction_response){
    transaction_response_xml(user)
  }
  let(:billing_info) {
    info = {}
    info[:first_name] = user.first_name
    info[:last_name] = user.last_name
    info[:address1] = 'Test Address 1'
    info[:address2] = 'Test Address 2'
    info[:city] = user.city
    info[:state] = user.state
    info[:country] = user.country
    info[:zip] = '12345'
    info[:number] = '4111-1111-1111-1111'
    info[:month] = '08'
    info[:year] = '2025'
    info[:verification_value] = '111'
    info
  }
  describe "using recurly API over internet" do
    it "fetches transactions created after GenericState.recurly_transactions_last_sync_at" do
      # pending("test this directly on recurly without stubbing. [maybe can omit as it tests recurly api?]")
      last_sync_at = Time.now
      WebMock.allow_net_connect!

      # create user account and subscription in recurly
      account1 = client.find_or_create_account(user, billing_info)
      subscription1 = client.create_subscription(user, 'jamsubgold', account1, starts_at = nil)
      subscription1.should_not be_nil

      expect { client.sync_transactions({ begin_time: last_sync_at.iso8601 }) }.to change(AffiliateDistribution, :count).by(1)
      AffiliateDistribution.order(:created_at).last.external_id.should_not be_nil
      AffiliateDistribution.order(:created_at).last.product_code.should_not be_nil

      GenericState.singleton.reload

      new_last_sync_at = GenericState.recurly_transactions_last_sync_at
      expect(last_sync_at < new_last_sync_at).to be true

      # create second user account and subscription in recurly
      account2 = client.find_or_create_account(user2, billing_info)
      subscription2 = client.create_subscription(user2, 'jamsubplatinumyearly', account2, starts_at = nil)

      GenericState.singleton.update_attribute(:recurly_transactions_last_sync_at, new_last_sync_at)
      expect { client.sync_transactions({ begin_time: new_last_sync_at.iso8601 }) }.to change(AffiliateDistribution, :count).by(1)
      AffiliateDistribution.order(:created_at).last.external_id.should_not be_nil
      AffiliateDistribution.order(:created_at).last.product_code.should_not be_nil
    end
  end
  describe "using mocked recurly" do
    before(:each) do
      #allow(recurly_transaction).to receive(:find_each).and_return(transaction) #works in rspec >=2.14

      WebMock.stub_request(:get, /recurly.com\/v2\/transactions\?\S+/).
          to_return(status: 200, body: transaction_response, headers: {})

      Recurly::Transaction.any_instance.stub(:subscriptions).and_return([
        Recurly::Subscription.new
      ])

      Recurly::Subscription.any_instance.stub(:plan).and_return(Recurly::Plan.new(plan_code: "jamsubgold"))
    end

    it "creates AffiliateDistribution records for successful recurring transactions" do
      expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(2)
    end

    # it "error out for when same transaction data been fetched" do
    #   expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(2)
    #   expect { client.sync_transactions }.to raise_error(ActiveRecord::RecordNotUnique)
    # end

    it "does not create AffiliateDistribution for same transaction previously been created" do
      expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(2)
      expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(0)
    end

    it "does not create AffiliateDistribution records when there is no affiliate partner" do
      user.affiliate_referral = nil
      user.save!
      AffiliateDistribution.delete_all
      transaction_response = transaction_response_xml(user)
      WebMock.stub_request(:get, /recurly.com\/v2\/transactions\?\S+/).
          to_return(status: 200, body: transaction_response, headers: {})
      expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(0)
    end

    it "does not create AffiliateDistribution if out of affiliate window" do
      AffiliateDistribution.delete_all
      transaction_response = lapse_transaction_response_xml(user)
      WebMock.stub_request(:get, /recurly.com\/v2\/transactions\?\S+/).
            to_return(status: 200, body: transaction_response, headers: {})
      #expect { client.sync_transactions }.to change(AffiliateDistribution, :count).by(0)
      client.sync_transactions
    end

    it "assigns correct affiliate partner" do
      client.sync_transactions
      AffiliateDistribution.all.each do |affiliate_distribution|
        expect(affiliate_distribution.affiliate_referral).to_not eq(nil)
        expect(affiliate_distribution.affiliate_referral).to eq(affiliate_partner)
      end
    end

    it "updates affiliate referral fee" do
      client.sync_transactions
      most_recently_created = AffiliateDistribution.order(created_at: :desc).first
      expect(most_recently_created.affiliate_referral_fee_in_cents).to_not eq(nil)
      expect(most_recently_created.affiliate_referral_fee_in_cents).to eq(27)
    end

    it "change affiliate rate and updates referral fee" do
      affiliate_partner.rate = 0.20
      affiliate_partner.save!
      client.sync_transactions
      most_recently_created = AffiliateDistribution.order(created_at: :desc).first
      expect(most_recently_created.affiliate_referral_fee_in_cents).to eq(18)
    end

    it "sets subscription product_type" do
      client.sync_transactions
      AffiliateDistribution.all.each do |affiliate_distribution|
        expect(affiliate_distribution.product_type).to_not eq(nil)
        expect(affiliate_distribution.product_type).to eq('Subscription')
      end
    end

    it "sets subscription product_code" do
      client.sync_transactions
      AffiliateDistribution.all.each do |affiliate_distribution|
        expect(affiliate_distribution.product_code).to_not eq(nil)
        expect(affiliate_distribution.product_code).to eq('jamsubgold')
      end
    end

    it "does not error out if begin_time is nil" do
      expect{ client.sync_transactions( { begin_time: nil } ) }.not_to raise_error
    end

    it "changes GenericState.recurly_transactions_last_sync_at" do
      before_time = GenericState.recurly_transactions_last_sync_at
      client.sync_transactions
      after_time = GenericState.recurly_transactions_last_sync_at
      expect(before_time).not_to eq(after_time)
    end
  end


end

def transaction_response_xml(user)
  <<-XMLDATA
    <transactions type="array">
    <transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4381" type="credit_card">
      <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
      <invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
      <subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4381/subscriptions"/>
      <uuid>374adcf4d716c1afc7b0b64bb79d4381</uuid>
      <action>purchase</action>
      <amount_in_cents type="integer">100</amount_in_cents>
      <tax_in_cents type="integer">9</tax_in_cents>
      <currency>USD</currency>
      <status>success</status>
      <payment_method>credit_card</payment_method>
      <reference>2216615</reference>
      <source>subscription</source>
      <recurring type="boolean">true</recurring>
      <test type="boolean">true</test>
      <voidable type="boolean">true</voidable>
      <refundable type="boolean">true</refundable>
      <ip_address>127.0.0.1</ip_address>
      <cvv_result code="" nil="nil"/>
      <avs_result code="D">Street address and postal code match.</avs_result>
      <avs_result_street nil="nil"/>
      <avs_result_postal nil="nil"/>
      <created_at type="datetime">#{10.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
      <updated_at type="datetime">#{10.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
      <details>
        <account>
          <account_code>#{user.id}</account_code>
          <first_name>Verena</first_name>
          <last_name>Example</last_name>
          <company>New Company Name</company>
          <email>verena@example.com</email>
          <billing_info type="credit_card">
            <first_name>Verena</first_name>
            <last_name>Example</last_name>
            <address1>123 Main St.</address1>
            <address2 nil="nil"/>
            <city>San Francisco</city>
            <state>CA</state>
            <zip>94105</zip>
            <country>US</country>
            <phone nil="nil"/>
            <vat_number nil="nil"/>
            <card_type>Visa</card_type>
            <year type="integer">2019</year>
            <month type="integer">12</month>
            <first_six>411111</first_six>
            <last_four>1111</last_four>
          </billing_info>
        </account>
      </details>
      <a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4381" method="delete"/>
    </transaction>

    <transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4382" type="credit_card">
      <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
      <invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
      <subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4382/subscriptions"/>
      <uuid>374adcf4d716c1afc7b0b64bb79d4382</uuid>
      <action>purchase</action>
      <amount_in_cents type="integer">200</amount_in_cents>
      <tax_in_cents type="integer">9</tax_in_cents>
      <currency>USD</currency>
      <status>success</status>
      <payment_method>credit_card</payment_method>
      <reference>2216615</reference>
      <source>subscription</source>
      <recurring type="boolean">true</recurring>
      <test type="boolean">true</test>
      <voidable type="boolean">true</voidable>
      <refundable type="boolean">true</refundable>
      <ip_address>127.0.0.1</ip_address>
      <cvv_result code="" nil="nil"/>
      <avs_result code="D">Street address and postal code match.</avs_result>
      <avs_result_street nil="nil"/>
      <avs_result_postal nil="nil"/>
      <created_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
      <updated_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
      <details>
        <account>
          <account_code>#{user.id}</account_code>
          <first_name>Verena</first_name>
          <last_name>Example</last_name>
          <company>New Company Name</company>
          <email>verena@example.com</email>
          <billing_info type="credit_card">
            <first_name>Verena</first_name>
            <last_name>Example</last_name>
            <address1>123 Main St.</address1>
            <address2 nil="nil"/>
            <city>San Francisco</city>
            <state>CA</state>
            <zip>94105</zip>
            <country>US</country>
            <phone nil="nil"/>
            <vat_number nil="nil"/>
            <card_type>Visa</card_type>
            <year type="integer">2019</year>
            <month type="integer">12</month>
            <first_six>411111</first_six>
            <last_four>1111</last_four>
          </billing_info>
        </account>
      </details>
      <a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4382" method="delete"/>
  </transaction>


  <transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4383" type="credit_card">
    <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
    <invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
    <subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4383/subscriptions"/>
    <uuid>374adcf4d716c1afc7b0b64bb79d4383</uuid>
    <action>purchase</action>
    <amount_in_cents type="integer">200</amount_in_cents>
    <tax_in_cents type="integer">9</tax_in_cents>
    <currency>USD</currency>
    <status>failed</status>
    <payment_method>credit_card</payment_method>
    <reference>2216615</reference>
    <source>transaction</source>
    <recurring type="boolean">true</recurring>
    <test type="boolean">true</test>
    <voidable type="boolean">true</voidable>
    <refundable type="boolean">true</refundable>
    <ip_address>127.0.0.1</ip_address>
    <cvv_result code="" nil="nil"/>
    <avs_result code="D">Street address and postal code match.</avs_result>
    <avs_result_street nil="nil"/>
    <avs_result_postal nil="nil"/>
    <created_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
    <updated_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
    <details>
      <account>
        <account_code>#{user.id}</account_code>
        <first_name>Verena</first_name>
        <last_name>Example</last_name>
        <company>New Company Name</company>
        <email>verena@example.com</email>
        <billing_info type="credit_card">
          <first_name>Verena</first_name>
          <last_name>Example</last_name>
          <address1>123 Main St.</address1>
          <address2 nil="nil"/>
          <city>San Francisco</city>
          <state>CA</state>
          <zip>94105</zip>
          <country>US</country>
          <phone nil="nil"/>
          <vat_number nil="nil"/>
          <card_type>Visa</card_type>
          <year type="integer">2019</year>
          <month type="integer">12</month>
          <first_six>411111</first_six>
          <last_four>1111</last_four>
        </billing_info>
      </account>
    </details>
    <a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4383" method="delete"/>
  </transaction>

  <transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4384" type="credit_card">
    <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
    <invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
    <subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4384/subscriptions"/>
    <uuid>374adcf4d716c1afc7b0b64bb79d4384</uuid>
    <action>purchase</action>
    <amount_in_cents type="integer">200</amount_in_cents>
    <tax_in_cents type="integer">9</tax_in_cents>
    <currency>USD</currency>
    <status>success</status>
    <payment_method>credit_card</payment_method>
    <reference>2216615</reference>
    <source>transaction</source>
    <recurring type="boolean">false</recurring>
    <test type="boolean">true</test>
    <voidable type="boolean">true</voidable>
    <refundable type="boolean">true</refundable>
    <ip_address>127.0.0.1</ip_address>
    <cvv_result code="" nil="nil"/>
    <avs_result code="D">Street address and postal code match.</avs_result>
    <avs_result_street nil="nil"/>
    <avs_result_postal nil="nil"/>
    <created_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
    <updated_at type="datetime">#{20.minutes.ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
    <details>
      <account>
        <account_code>#{user.id}</account_code>
        <first_name>Verena</first_name>
        <last_name>Example</last_name>
        <company>New Company Name</company>
        <email>verena@example.com</email>
        <billing_info type="credit_card">
          <first_name>Verena</first_name>
          <last_name>Example</last_name>
          <address1>123 Main St.</address1>
          <address2 nil="nil"/>
          <city>San Francisco</city>
          <state>CA</state>
          <zip>94105</zip>
          <country>US</country>
          <phone nil="nil"/>
          <vat_number nil="nil"/>
          <card_type>Visa</card_type>
          <year type="integer">2019</year>
          <month type="integer">12</month>
          <first_six>411111</first_six>
          <last_four>1111</last_four>
        </billing_info>
      </account>
    </details>
    <a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4384" method="delete"/>
</transaction>

  </transactions>
XMLDATA
end

def lapse_transaction_response_xml(user)
  <<-XMLDATA
    <transactions type="array">
    <transaction href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4385" type="credit_card">
      <account href="https://your-subdomain.recurly.com/v2/accounts/1"/>
      <invoice href="https://your-subdomain.recurly.com/v2/invoices/1005"/>
      <subscriptions href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4385/subscriptions"/>
      <uuid>374adcf4d716c1afc7b0b64bb79d4385</uuid>
      <action>purchase</action>
      <amount_in_cents type="integer">100</amount_in_cents>
      <tax_in_cents type="integer">9</tax_in_cents>
      <currency>USD</currency>
      <status>success</status>
      <payment_method>credit_card</payment_method>
      <reference>2216615</reference>
      <source>transaction</source>
      <recurring type="boolean">true</recurring>
      <test type="boolean">true</test>
      <voidable type="boolean">true</voidable>
      <refundable type="boolean">true</refundable>
      <ip_address>127.0.0.1</ip_address>
      <cvv_result code="" nil="nil"/>
      <avs_result code="D">Street address and postal code match.</avs_result>
      <avs_result_street nil="nil"/>
      <avs_result_postal nil="nil"/>
      <created_at type="datetime">#{(365.days + 1.day).ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</created_at>
      <updated_at type="datetime">#{(365.days + 1.day).ago.strftime('%Y-%m-%dT%H:%M:%SZ')}</updated_at>
      <details>
        <account>
          <account_code>#{user.id}</account_code>
          <first_name>Verena</first_name>
          <last_name>Example</last_name>
          <company>New Company Name</company>
          <email>verena@example.com</email>
          <billing_info type="credit_card">
            <first_name>Verena</first_name>
            <last_name>Example</last_name>
            <address1>123 Main St.</address1>
            <address2 nil="nil"/>
            <city>San Francisco</city>
            <state>CA</state>
            <zip>94105</zip>
            <country>US</country>
            <phone nil="nil"/>
            <vat_number nil="nil"/>
            <card_type>Visa</card_type>
            <year type="integer">2019</year>
            <month type="integer">12</month>
            <first_six>411111</first_six>
            <last_four>1111</last_four>
          </billing_info>
        </account>
      </details>
      <a name="refund" href="https://your-subdomain.recurly.com/v2/transactions/374adcf4d716c1afc7b0b64bb79d4385" method="delete"/>
    </transaction>

  </transactions>
XMLDATA
end