class TutoringSessionsController < ApplicationController
  before_filter :require_login
  before_filter :find_tutoring_session, only: [:edit, :update, :rating, :rate_and_pay, :mark_unoccured, :rate]
  before_filter :verify_student, only: [:rating, :rate_and_pay, :mark_unoccured, :rate]
  skip_before_filter :check_for_previous_confirmed_sessions, only: [:rate, :rating, :rate_and_pay, :mark_unoccured]

  def select_tutor_to_book_session
    if params[:other_user]
      @other_user = User.find(params[:other_user])
      if @other_user.tutor?
        @tutoring_session = TutoringSession.new(tutor_id: @other_user.id)
      end
    end
    render layout: false
  end

  # Show related sessions of the current user.
  def show
    @tutoring_session = current_user.related_sessions.find(params[:id])
    render layout: false
  end

  # Edit the tutoring sessions
  def edit
    @tutor = @tutoring_session.tutor
    @tutoring_session.attachments.build unless @tutoring_session.attachments.exists?
    render layout: false
  end

  # Find and update tutoring session
  def update
    respond_to do |format|
      if @tutoring_session.update_attributes(tutoring_session_params)
        @tutoring_session.send_tutoring_session_update_mail
        format.js {}
      else
        format.js {render partial: 'form', locals: {tutoring_session: @tutoring_session}, replace: "form#edit_tutoring_session_#{@tutoring_session.id}"}
      end
    end
  end

  # Get all the tutoring session, courses and events between start date and end date related to current user.
  def index
    unless params[:view] == 'list'
      @start_date = Date.parse(params[:start])
      @end_date = Date.parse(params[:end])
    end
    if params[:other_user].present?
      @other_user = User.find_by_id(params[:other_user])
      @other_user_tutoring_sessions = @other_user.related_sessions(start_date: @start_date, end_date: @end_date).not_rejected
      @other_user_schedule_events = @other_user.events.responded_by_user(@other_user).except_rejected_by(@other_user).for_date_range(@start_date, @end_date)
      if @other_user.tutor?
        @other_user_availabilities = @other_user.availability_for(@start_date, @end_date)
      end
    end
    unless params[:view]
      @tutoring_sessions = current_user.related_sessions(start_date: @start_date, end_date: @end_date).not_rejected
      @tutoring_sessions = @tutoring_sessions.includes(:invoice, :user).not_offline
      @schedule_events = current_user.events.responded_by_user(current_user).except_rejected_by(current_user).for_date_range(@start_date, @end_date)
      if current_user.tutor?
        @availabilities = current_user.availability_for(@start_date, @end_date)
      end
    else
      if params[:view] == 'list'
        associations = [:tutor, :user, :resource, :invoice, :messages]
        @tutoring_sessions = current_user.related_sessions.not_offline.includes(*associations)
        @tutoring_sessions = @tutoring_sessions.page(params[:page]).per(params[:per_page])
      end
    end
    respond_to do |format|
      format.html do
        render partial: "#{params[:view]}_view" if params[:view]
      end
      format.json
    end
  end

  # Returns pending and confirmed sessions.
  def upcoming
    sessions = {pending: [], confirmed: []}
    current_user.related_sessions.upcoming.rejected.includes(:user, :tutor).each do |session|
      if session.pending?
        sessions[:pending] << session.for_appointment_sidebar
      else
        sessions[:confirmed] << session.for_appointment_sidebar
      end
    end
    respond_to do |format|
      format.json {render json: sessions}
    end
  end

  # Build review for tutoring sessions.
  def rating
    @tutoring_session.build_review unless @tutoring_session.review
    @tutoring_session.build_session_omitted_reason unless @tutoring_session.session_omitted_reason
    @tutoring_session.invoice
    render layout: false
  end

  # Add review for tutoring session.(i.e. rate the session)
  def rate
    save_review
    respond_to do |format|
      format.js { redirect_via_turbolinks_to dashboard_path}
      format.html {redirect_to dashboard_path }
    end
  end

  # Find or create invoice for tutoring sessions and if not paid it proceed for payment.
  def rate_and_pay
    @invoice = @tutoring_session.find_or_create_invoice!
    unless @invoice.paid?
      confirm_session!
      if @invoice.pay_tutor
        save_review
        respond_to do |format|
          format.js {}
        end
      else
        if @invoice.manually_billed? or @tutoring_session.video_session?
          message = "Your amount for this invoice has been transfered to #{Configurations::General.application_name} escrow account. But unable to make payment to the #{Tutor.model_name.human}. Please contact #{Configurations::General.application_name} team."
        else
          message = "Unable to make payment to #{Tutor.model_name.human}. Please contact #{Configurations::General.application_name} team."
        end
        redirect_to request.referer || root_path, notice: message
      end
    else
      redirect_to dashboard_path, notice: 'This session has already been paid.'
    end
  end

  # Used to mark session unoccured(i.e. session that is omitted by some reason) only if it is not paid.
  def mark_unoccured
    respond_to do |format|
      unless @tutoring_session.paid?
        if @tutoring_session.update_attributes(mark_unoccured_params)
          format.js {}
        else
          format.js {render partial: 'session_omitted_reason', within: "#session-omitted-reason"}
        end
      else
        redirect_to dashboard_path, notice: 'This session has already been paid.'
      end
    end
  end

  private

  def save_review
    review = @tutoring_session.review || @tutoring_session.build_review
    review.attributes = review_params
    review.save
  end

  def confirm_session!
    if (@invoice.manually_billed? or @tutoring_session.video_session?) and !@tutoring_session.confirmed?
      if Charge.charge_for @tutoring_session
        @tutoring_session.confirm!
      else
        redirect_to root_path, notice: "Unable to charge your card. Please contact #{Configurations::General.application_name} team." and return
      end
    end
  end

  def review_params
    params[:tutoring_session].required(:review_attributes).permit(:helpfulness, :timeliness, :knowledge, :friendliness, :id).merge(user: current_user, for_user: @tutoring_session.tutor)
  end

  def find_tutoring_session
    @tutoring_session = current_user.tutored_sessions.find(params[:id])
  end

  def verify_student
    unless @tutoring_session.user == current_user
      raise ActiveRecord::RecordNotFound
    end
  end

  def tutoring_session_params
    params.required(:tutoring_session).permit(:start, :end, :date, :category_id, :subject_id, :on_site, :location, :resource_id, :message, attachments_attributes: [:attachment, :id, :_destroy])
  end

  def mark_unoccured_params
    params.required(:tutoring_session).permit(session_omitted_reason_attributes: [:reason, :other_reason])
  end
end
