=begin

require 'spec_helper'

describe "TestDrive Lesson Flow" do

  let(:user) { FactoryGirl.create(:user, remaining_test_drives: 0) }

  let(:teacher_user) { FactoryGirl.create(:teacher_user) }
  let(:teacher_user2) { FactoryGirl.create(:teacher_user) }
  let(:teacher) { teacher_user.teacher }
  let(:lesson_booking_slot_single1) { FactoryGirl.build(:lesson_booking_slot_single) }
  let(:lesson_booking_slot_single2) { FactoryGirl.build(:lesson_booking_slot_single) }
  let(:lesson_booking_slot_recurring1) { FactoryGirl.build(:lesson_booking_slot_recurring) }
  let(:lesson_booking_slot_recurring2) { FactoryGirl.build(:lesson_booking_slot_recurring) }
  let(:valid_single_slots) { [lesson_booking_slot_single1, lesson_booking_slot_single2] }
  let(:valid_recurring_slots) { [lesson_booking_slot_recurring1, lesson_booking_slot_recurring2] }
  let(:affiliate_partner) { FactoryGirl.create(:affiliate_partner) }
  let(:affiliate_partner2) { FactoryGirl.create(:affiliate_partner, lesson_rate: 0.30) }
  let(:school) { FactoryGirl.create(:school) }
  let(:card_lessons) {FactoryGirl.create(:posa_card_lesson_4)}
  let(:retailer) {FactoryGirl.create(:retailer)}

  before {
    teacher.stripe_account_id = stripe_account1_id
    teacher.save!
  }
  after {
    Timecop.return
  }

  it "works" do

    user.desired_package = LessonPackageType.test_drive_2
    user.save!

    # user has no test drives, no credit card on file, but attempts to book a lesson
    booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.")
    booking.errors.any?.should be_false
    booking.card_presumed_ok.should be_false
    booking.user.should eql user
    booking.card_presumed_ok.should be_false
    booking.should eql user.unprocessed_test_drive
    booking.sent_notices.should be_false
    teacher_user.has_booked_test_drive_with_student?(user).should be_true

    user.reload
    user.remaining_test_drives.should eql 0

    ##########  Need validate their credit card
    token = create_stripe_token
    result = user.payment_update({token: token, zip: '78759', test_drive: true, booking_id: booking.id})
    booking = result[:lesson]
    booking.errors.any?.should be_false
    lesson = booking.lesson_sessions[0]

    lesson.errors.any?.should be_false
    test_drive = result[:test_drive]
    test_drive.errors.any?.should be_false

    user.reload
    user.remaining_test_drives.should eql 1

    booking.card_presumed_ok.should be_true
    booking.sent_notices.should be_true
    lesson.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
    lesson.reload


    test_drive.stripe_charge_id.should_not be_nil
    test_drive.recurly_tax_in_cents.should be 247
    test_drive.recurly_total_in_cents.should eql 2999 + 247
    test_drive.recurly_subtotal_in_cents.should eql 2999
    test_drive.recurly_currency.should eql 'USD'
    line_item = test_drive.sale_line_items[0]
    line_item.quantity.should eql 1
    line_item.product_type.should eql SaleLineItem::LESSON
    line_item.product_id.should eq LessonPackageType.test_drive_2.id
    user.reload
    user.stripe_customer_id.should_not be nil
    user.lesson_purchases.length.should eql 1
    user.remaining_test_drives.should eql 1
    lesson_purchase = user.lesson_purchases[0]
    lesson_purchase.price.should eql 29.99
    lesson_purchase.lesson_package_type.is_test_drive?.should eql true

    customer = Stripe::Customer.retrieve(user.stripe_customer_id)
    customer.email.should eql user.email

    booking.lesson_sessions.length.should eql 1
    lesson_session = booking.lesson_sessions[0]
    lesson_session.status.should eql LessonBooking::STATUS_REQUESTED
    booking.status.should eql LessonBooking::STATUS_REQUESTED

    ######### Teacher counters with new slot
    teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 14)
    UserMailer.deliveries.clear
    lesson_session.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'})
    booking.reload
    booking.errors.any?.should be false
    lesson_session.lesson_booking.errors.any?.should be false
    lesson_session.lesson_booking_slots.length.should eql 1
    lesson_session.lesson_booking_slots[0].proposer.should eql teacher_user
    teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
    teacher_counter.should eql teacher_countered_slot
    teacher_counter.proposer.should eql teacher_user
#    booking.lesson_booking_slots.length.should eql 3
    UserMailer.deliveries.length.should eql 1
    chat = ChatMessage.unscoped.order(:created_at).last
    chat.channel.should eql ChatMessage::CHANNEL_LESSON
    chat.message.should eql 'Does this work?'
    chat.user.should eql teacher_user
    chat.target_user.should eql user
    notification = Notification.unscoped.order(:created_at).last
    notification.session_id.should eql lesson_session.music_session.id
    notification.student_directed.should eql true
    notification.purpose.should eql 'counter'
    notification.description.should eql NotificationTypes::LESSON_MESSAGE

    ######### Student counters with new slot
    student_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 16)
    UserMailer.deliveries.clear
    lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
    lesson_session.errors.any?.should be false
    lesson_session.lesson_booking.errors.any?.should be false
    lesson_session.lesson_booking_slots.length.should eql 2
    student_counter = booking.lesson_booking_slots.order(:created_at).last
    student_counter.proposer.should eql user
    booking.reload
#    booking.lesson_booking_slots.length.should eql 4
    UserMailer.deliveries.length.should eql 1
    chat = ChatMessage.unscoped.order(:created_at).last
    chat.message.should eql 'Does this work better?'
    chat.channel.should eql ChatMessage::CHANNEL_LESSON
    chat.user.should eql user
    chat.target_user.should eql teacher_user
    notification = Notification.unscoped.order(:created_at).last
    notification.session_id.should eql lesson_session.music_session.id
    notification.student_directed.should eql false
    notification.purpose.should eql 'counter'
    notification.description.should eql NotificationTypes::LESSON_MESSAGE

    ######## Teacher accepts slot
    UserMailer.deliveries.clear

    lesson_session.accept({message: 'Yeah I got this', slot: student_counter.id, update_all: false, accepter: teacher_user})
    lesson_session.errors.any?.should be_false
    lesson_session.reload
    lesson_session.slot.should eql student_counter
    lesson_session.status.should eql LessonSession::STATUS_APPROVED
    booking.reload
    booking.default_slot.should eql student_counter
    lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
    booking.status.should eql LessonBooking::STATUS_APPROVED

    UserMailer.deliveries.length.should eql 2
    chat = ChatMessage.unscoped.order(:created_at).last
    chat.message.should eql 'Yeah I got this'
    chat.channel.should eql ChatMessage::CHANNEL_LESSON
    chat.user.should eql teacher_user
    chat.target_user.should eql user
    notification = Notification.unscoped.order(:created_at).last
    notification.session_id.should eql lesson_session.music_session.id
    notification.student_directed.should eql true
    notification.purpose.should eql 'accept'
    notification.description.should eql NotificationTypes::LESSON_MESSAGE
    notification.message.should be_nil


    # teacher & student get into session
    start = lesson_session.scheduled_start
    end_time = lesson_session.scheduled_start + (60 * lesson_session.duration)
    uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time)
    # artificially end the session, which is covered by other background jobs
    lesson_session.music_session.session_removed_at = end_time
    lesson_session.music_session.save!

    Timecop.travel(end_time + 1)


    UserMailer.deliveries.clear
    # background code comes around and analyses the session
    lesson.analyse
    lesson.session_completed
    lesson_session.reload
    lesson_session.analysed.should be_true
    analysis = lesson_session.analysis
    analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
    analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
    lesson_session.billed.should be false
    if lesson_session.billing_error_detail
      puts "testdrive flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
    end
    lesson_session.billing_error_reason.should be_nil
    lesson_session.sent_notices.should be true
    purchase = lesson_session.lesson_package_purchase
    purchase.should_not be_nil
    purchase.price_in_cents.should eql 2999
    purchase.lesson_package_type.is_test_drive?.should be true
    user.reload
    user.remaining_test_drives.should eql 1
    UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
    found_student_email = false
    UserMailer.deliveries.each do |d|
      if d.subject == "You have used 1 of 2 TestDrive lesson credits"
        found_student_email = true
      end
    end
    found_student_email.should be_true

    teacher_distribution = lesson_session.teacher_distribution
    teacher_distribution.amount_in_cents.should eql 1000
    teacher_distribution.ready.should be_true
    teacher_distribution.distributed.should be_false

    LessonBooking.hourly_check
    LessonSession.hourly_check

    teacher_distribution.reload
    teacher_distribution.amount_in_cents.should eql 1000
    teacher_distribution.ready.should be_true
    teacher_distribution.distributed.should be_false

    TeacherPayment.count.should eql 0
    TeacherPayment.hourly_check
    TeacherPayment.count.should eql 1

    lesson_session.reload
    purchase.reload

    purchase.teacher_distribution.should be_nil

    teacher_payment = TeacherPayment.first
    teacher_payment.amount_in_cents.should eql 1000
    teacher_payment.fee_in_cents.should eql 0
    teacher_payment.teacher.should eql teacher_user

    teacher_distribution.reload
    teacher_distribution.amount_in_cents.should eql 1000
    teacher_distribution.ready.should be_true
    teacher_distribution.distributed.should be_true

    teacher_payment.teacher_payment_charge.amount_in_cents.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round
    teacher_payment.teacher_payment_charge.fee_in_cents.should eql 0

    user.sales.count.should eql 1
    sale = user.sales[0]
    sale.sale_line_items.count.should eql 1
    sale.sale_line_items[0].affiliate_distributions.count.should eql 0

    lesson_session.lesson_booking.status.should eql LessonBooking::STATUS_COMPLETED
    lesson_session.lesson_booking.success.should be_true
    LessonBooking.bookings(user, teacher_user, nil).count.should eql 1
    LessonBooking.engaged_bookings(user, teacher_user, nil).count.should eql 1
    teacher_user.has_booked_test_drive_with_student?(user).should be_true

    booking.reload
    booking.lesson_sessions.length.should eql 1
  end

  it "works using posa card" do

    PosaCard.activate(card_lessons, retailer)
    card_lessons.reload
    card_lessons.claim(user)
    card_lessons.errors.any?.should be false

    user.reload
    user.jamclass_credits.should eql 4


    # user has no test drives, no credit card on file, but attempts to book a lesson
    booking = LessonBooking.book_test_drive(user, teacher_user, valid_single_slots, "Hey I've heard of you before.")
    booking.errors.any?.should be_false
    booking.card_presumed_ok.should be_false
    booking.user.should eql user
    booking.sent_notices.should be_true
    booking.posa_card.should eql card_lessons
    booking.posa_card_purchased.should be_true
    user.unprocessed_test_drive.should be_nil
    teacher_user.has_booked_test_drive_with_student?(user).should be_true

    user.reload
    user.jamclass_credits.should eql 3
    lesson_session = booking.lesson_sessions[0]
    lesson_session.posa_card.should eql card_lessons
    lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
    lesson_session.reload

    #booking.lesson_package_purchases.should eql [card_lessons.lesson_package_purchase]
    user.stripe_customer_id.should be nil
    user.lesson_purchases.length.should eql 1
    lesson_purchase = user.lesson_purchases[0]
    lesson_purchase.price.should eql 49.99
    lesson_purchase.lesson_package_type.is_test_drive?.should eql true
    lesson_purchase.posa_card.should eql card_lessons
    lesson_session.status.should eql LessonBooking::STATUS_REQUESTED
    booking.status.should eql LessonBooking::STATUS_REQUESTED

    ######### Teacher counters with new slot
    teacher_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 14)
    UserMailer.deliveries.clear
    lesson_session.counter({proposer: teacher_user, slot: teacher_countered_slot, message: 'Does this work?'})
    booking.reload
    booking.errors.any?.should be false
    lesson_session.lesson_booking.errors.any?.should be false
    lesson_session.lesson_booking_slots.length.should eql 1
    lesson_session.lesson_booking_slots[0].proposer.should eql teacher_user
    teacher_counter = lesson_session.lesson_booking_slots.order(:created_at).last
    teacher_counter.should eql teacher_countered_slot
    teacher_counter.proposer.should eql teacher_user
#    booking.lesson_booking_slots.length.should eql 3
    UserMailer.deliveries.length.should eql 1
    chat = ChatMessage.unscoped.order(:created_at).last
    chat.channel.should eql ChatMessage::CHANNEL_LESSON
    chat.message.should eql 'Does this work?'
    chat.user.should eql teacher_user
    chat.target_user.should eql user
    notification = Notification.unscoped.order(:created_at).last
    notification.session_id.should eql lesson_session.music_session.id
    notification.student_directed.should eql true
    notification.purpose.should eql 'counter'
    notification.description.should eql NotificationTypes::LESSON_MESSAGE

    ######### Student counters with new slot
    student_countered_slot = FactoryGirl.build(:lesson_booking_slot_single, hour: 16)
    UserMailer.deliveries.clear
    lesson_session.counter({proposer: user, slot: student_countered_slot, message: 'Does this work better?'})
    lesson_session.errors.any?.should be false
    lesson_session.lesson_booking.errors.any?.should be false
    lesson_session.lesson_booking_slots.length.should eql 2
    student_counter = booking.lesson_booking_slots.order(:created_at).last
    student_counter.proposer.should eql user
    booking.reload
#    booking.lesson_booking_slots.length.should eql 4
    UserMailer.deliveries.length.should eql 1
    chat = ChatMessage.unscoped.order(:created_at).last
    chat.message.should eql 'Does this work better?'
    chat.channel.should eql ChatMessage::CHANNEL_LESSON
    chat.user.should eql user
    chat.target_user.should eql teacher_user
    notification = Notification.unscoped.order(:created_at).last
    notification.session_id.should eql lesson_session.music_session.id
    notification.student_directed.should eql false
    notification.purpose.should eql 'counter'
    notification.description.should eql NotificationTypes::LESSON_MESSAGE

    ######## Teacher accepts slot
    UserMailer.deliveries.clear

    lesson_session.accept({message: 'Yeah I got this', slot: student_counter.id, update_all: false, accepter: teacher_user})
    lesson_session.errors.any?.should be_false
    lesson_session.reload
    lesson_session.slot.should eql student_counter
    lesson_session.status.should eql LessonSession::STATUS_APPROVED
    booking.reload
    booking.default_slot.should eql student_counter
    lesson_session.music_session.scheduled_start.should eql booking.default_slot.scheduled_time(0)
    booking.status.should eql LessonBooking::STATUS_APPROVED

    UserMailer.deliveries.length.should eql 2
    chat = ChatMessage.unscoped.order(:created_at).last
    chat.message.should eql 'Yeah I got this'
    chat.channel.should eql ChatMessage::CHANNEL_LESSON
    chat.user.should eql teacher_user
    chat.target_user.should eql user
    notification = Notification.unscoped.order(:created_at).last
    notification.session_id.should eql lesson_session.music_session.id
    notification.student_directed.should eql true
    notification.purpose.should eql 'accept'
    notification.description.should eql NotificationTypes::LESSON_MESSAGE
    notification.message.should be_nil


    # teacher & student get into session
    start = lesson_session.scheduled_start
    end_time = lesson_session.scheduled_start + (60 * lesson_session.duration)
    uh2 = FactoryGirl.create(:music_session_user_history, user: teacher_user, history: lesson_session.music_session, created_at: start, session_removed_at: end_time)
    # artificially end the session, which is covered by other background jobs
    lesson_session.music_session.session_removed_at = end_time
    lesson_session.music_session.save!

    Timecop.travel(end_time + 1)


    UserMailer.deliveries.clear
    # background code comes around and analyses the session
    lesson_session.analyse
    lesson_session.session_completed
    lesson_session.reload
    lesson_session.analysed.should be_true
    analysis = lesson_session.analysis
    analysis["reason"].should eql LessonSessionAnalyser::STUDENT_FAULT
    analysis["student"].should eql LessonSessionAnalyser::NO_SHOW
    lesson_session.billed.should be false
    if lesson_session.billing_error_detail
      puts "testdrive flow #{lesson_session.billing_error_detail}" # this should not occur, but helps a great deal if a regression occurs and running all the tests
    end
    lesson_session.billing_error_reason.should be_nil
    lesson_session.sent_notices.should be true
    purchase = lesson_session.lesson_package_purchase
    purchase.should_not be_nil
    purchase.price_in_cents.should eql 4999
    purchase.lesson_package_type.is_test_drive?.should be true
    user.reload
    user.remaining_test_drives.should eql 0
    UserMailer.deliveries.length.should eql 2 # one for student, one for teacher
    found_student_email = false
    UserMailer.deliveries.each do |d|
      if d.subject == "You have used 1 of 4 TestDrive lesson credits"
        found_student_email = true
      end
    end
    found_student_email.should be_true

    teacher_distribution = lesson_session.teacher_distribution
    teacher_distribution.amount_in_cents.should eql 1000
    teacher_distribution.ready.should be_true
    teacher_distribution.distributed.should be_false

    LessonBooking.hourly_check
    LessonSession.hourly_check

    teacher_distribution.reload
    teacher_distribution.amount_in_cents.should eql 1000
    teacher_distribution.ready.should be_true
    teacher_distribution.distributed.should be_false

    TeacherPayment.count.should eql 0
    TeacherPayment.hourly_check
    TeacherPayment.count.should eql 1

    lesson_session.reload
    purchase.reload

    purchase.teacher_distribution.should be_nil

    teacher_payment = TeacherPayment.first
    teacher_payment.amount_in_cents.should eql 1000
    teacher_payment.fee_in_cents.should eql 0
    teacher_payment.teacher.should eql teacher_user

    teacher_distribution.reload
    teacher_distribution.amount_in_cents.should eql 1000
    teacher_distribution.ready.should be_true
    teacher_distribution.distributed.should be_true

    teacher_payment.teacher_payment_charge.amount_in_cents.should eql (1000 + 1000 * APP_CONFIG.stripe[:ach_pct]).round
    teacher_payment.teacher_payment_charge.fee_in_cents.should eql 0

    user.sales.count.should eql 1
    sale = user.sales[0]
    sale.sale_line_items.count.should eql 1
    sale.sale_line_items[0].affiliate_distributions.count.should eql 0

    lesson_session.lesson_booking.status.should eql LessonBooking::STATUS_COMPLETED
    lesson_session.lesson_booking.success.should be_true
    LessonBooking.bookings(user, teacher_user, nil).count.should eql 1
    LessonBooking.engaged_bookings(user, teacher_user, nil).count.should eql 1
    teacher_user.has_booked_test_drive_with_student?(user).should be_true
  end

  # VRFS-4069
  it "cancels with no credit card" do

    slots = []
    slots << FactoryGirl.build(:lesson_booking_slot_single)
    slots << FactoryGirl.build(:lesson_booking_slot_single)

    booking = LessonBooking.book_test_drive(user, teacher_user, slots, "Hey I've heard of you before.")

    booking.errors.any?.should be_false
    lesson = booking.lesson_sessions[0]
    booking.card_presumed_ok.should be_false

    user.reload
    user.remaining_test_drives.should eql 0

    lesson.cancel({canceler: user, message: "sorry about that"})

    user.reload

    user.remaining_test_drives.should eql 0
    booking.reload
    booking.status.should eql LessonBooking::STATUS_CANCELED
    teacher_user.has_booked_test_drive_with_student?(user).should be_false
  end

  it "cancels with credit card" do
    lesson = testdrive_lesson(user, teacher_user)

    user.reload
    user.remaining_test_drives.should eql 3

    lesson.cancel({canceler: user, message: "sorry about that"})

    user.reload

    user.remaining_test_drives.should eql 4
  end

  it "post-lesson emails" do
    UserMailer.deliveries.clear
    lesson = testdrive_lesson(user, teacher_user, {accept:true, success: true})

    user.reload
    user.remaining_test_drives.should eql 3

    found_student_email = false
    UserMailer.deliveries.each do |d|
      if d.subject == "You have used 1 of 4 TestDrive lesson credits"
        found_student_email = true
      end
    end
    found_student_email.should be_true
  end

  # tests that the correct emails are sent out after test drives are done
  it "both no show, then student no shows" do
    UserMailer.deliveries.clear
    lesson = testdrive_lesson(user, teacher_user, {accept: true, miss: true, package_count: 2})
    found_no_credit_email = false
    found_no_success_email = false
    UserMailer.deliveries.each do |d|
      if d.subject == "Your TestDrive with #{teacher_user.name} will not use a credit"
        found_no_credit_email = true
      end
      if d.subject == "Your TestDrive with #{user.name} was not successful"
        found_no_success_email = true
      end
    end

    found_no_credit_email.should be_true
    found_no_success_email.should be_true

    UserMailer.deliveries.clear
    user.reload
    user.remaining_test_drives.should eql 2

    lesson = testdrive_lesson(user, teacher_user, {accept: true, finish: true})

    user.reload
    user.remaining_test_drives.should eql 1

    completed_test_drive = false
    done_not_completed = false
    paid_but_no_show = false
    UserMailer.deliveries.each do |d|
      if d.subject == "You have used #{user.remaining_test_drives} of #{user.total_test_drives} TestDrive lesson credits"
        done_not_completed = true
      end
      if d.subject == "You have used all TestDrive lesson credits"
        completed_test_drive = true
      end
      if d.subject == "You successfully completed a lesson with #{user.name}"
        paid_but_no_show = true
      end
    end
    done_not_completed.should be_true
    paid_but_no_show.should be_true
    completed_test_drive.should be_false

    UserMailer.deliveries.clear

    # now use last credit
    lesson = testdrive_lesson(user, teacher_user2, {accept: true, finish: true, student_show: true})

    user.reload
    user.remaining_test_drives.should eql 0

    completed_test_drive = true
    paid = false
    UserMailer.deliveries.each do |d|
      if d.subject == "You have used all TestDrive lesson credits"
        completed_test_drive = true
      end
      if d.subject == "You successfully completed a lesson with #{user.name}"
        paid = true
      end
    end

      # You successfully completed a lesson with #{@student.name}"
    completed_test_drive.should be_true
    paid.should be_true
  end
end

=end