class Admin::Accounting::Billing::TemplatesController < Admin::Accounting::Controller
  def index
    render_success :ok, json: templates.map { |t| template_props(t) }
  end

  def show
    render_success :ok, json: template_props(template)
  end

  def create
    template = templates.build(template_params)
    if template.save
      render_success :ok, json: { id: template.id }
    else
      render_error :unprocessable_entity, errors: template
    end
  end

  def update
    if template.update(template_params)
      render_success :ok
    else
      render_error :unprocessable_entity, errors: template
    end
  end

  def destroy
    if template.destroy
      render_success :ok
    else
      render_error :unprocessable_entity, errors: template
    end
  end

  def attach
    plans = []

    students.each do |student|
      plan = billing_plan(student)
      plan.details = (plan.transaction_details + template_details).uniq
      plans << plan
    end

    if transactional_save(plans)
      render_success :ok, message: 'Template attached'
    else
      render_error :unprocessable_entity, message: 'Something went wrong'
    end
  end

  def detach
    plans = []

    students.each do |student|
      plan = billing_plan(student)
      plan.details = plan.transaction_details - template_details
      plans << plan
    end

    if transactional_save(plans)
      render_success :ok, message: 'Template detached'
    else
      render_error :unprocessable_entity, message: 'Something went wrong'
    end
  end

  private
    def templates
      current_school.billing_templates
        .includes(:school_year)
        .by_school_year(params[:school_year_id])
        .order(:name)
    end

    def template
      @template ||= templates.find_by(id: params[:id])
    end

    def student_count
      @student_count ||= current_school.billing_plans
        .joins(transaction_details: :template_transaction)
        .group('billing_template_transactions.template_id')
        .distinct
        .count
    end

    def students
      current_school.students
        .includes(billing_plans: :transaction_details)
        .where(id: params[:student_ids])
    end

    def billing_plan(student)
      plan_by_student[student.id] || student.billing_plans.build(school_year: template.school_year)
    end

    def plan_by_student
      @plan_by_student ||= current_school.billing_plans
        .by_student(params[:student_ids])
        .by_school_year(template.school_year)
        .index_by(&:student_id)
    end

    def school_year
      @school_year ||= current_school.school_years.find_by(id: params[:school_year_id])
    end

    def template_details
      template.transaction_details
    end

    def template_params
      params.permit(:name).merge(set_associations)
    end

    def set_associations
      {}.tap do |prop|
        prop[:school_year] = school_year
      end
    end

    def template_props(template)
      {
        id: template.id,
        name: template.name,
        school_year_id: template.school_year_id,
        school_year_name: template.school_year&.name,
        student_count: student_count[template.id] || 0
      }
    end
end
