require 'test_helper'

class PostsControllerTest < ActionController::TestCase
  include Devise::Test::ControllerHelpers

  test 'can create category post' do
    sign_in users(:standard_user)

    try_create_post

    assert_response(:found)
    assert_not_nil assigns(:post).id
    assert_redirected_to post_path(assigns(:post))
  end

  test 'can create answer' do
    sign_in users(:closer)

    before_notifs = posts(:question_one).user.notifications.count
    try_create_post(post_type: post_types(:answer), parent: posts(:question_one))
    after_notifs = posts(:question_one).user.notifications.count

    assert_response(:found)
    assert_not_nil assigns(:post).id
    assert_equal before_notifs + 1, after_notifs, 'Notification not created on answer create'
    assert_redirected_to post_path(posts(:question_one).id, anchor: "answer-#{assigns(:post).id}")
  end

  test 'create requires authentication' do
    try_create_post
    assert_redirected_to_sign_in
  end

  test 'can create help post' do
    sign_in users(:moderator)

    post :create, params: { post_type: post_types(:help_doc).id,
                            post: { post_type_id: post_types(:help_doc).id, title: sample.title, doc_slug: 'topic',
                                    body_markdown: sample.body_markdown, help_category: 'A', help_ordering: '99' } }

    assert_response(:found)
    assert_not_nil assigns(:post).id
    assert_redirected_to help_path(assigns(:post).doc_slug)
  end

  test 'standard users cannot create help posts' do
    sign_in users(:standard_user)

    post :create, params: { post_type: post_types(:help_doc).id,
                            post: { post_type_id: post_types(:help_doc).id, title: sample.title, doc_slug: 'topic',
                                    body_markdown: sample.body_markdown, help_category: 'A', help_ordering: '99' } }

    assert_response(:not_found)
  end

  test 'moderators cannot create policy posts' do
    sign_in users(:moderator)

    post :create, params: { post_type: post_types(:policy_doc).id,
                            post: { post_type_id: post_types(:policy_doc).id, title: sample.title, doc_slug: 'topic',
                                    body_markdown: sample.body_markdown, help_category: 'A', help_ordering: '99' } }

    assert_response(:not_found)
  end

  test 'category post type rejects without category' do
    sign_in users(:standard_user)

    try_create_post(category: nil)

    assert_response(:found)
    assert_redirected_to root_path
    assert_not_nil flash[:danger]
    assert_nil assigns(:post).id
  end

  test 'category post type checks required trust level' do
    sign_in users(:standard_user)

    try_create_post(category: categories(:high_trust))

    assert_response(:forbidden)
    assert_nil assigns(:post).id
    assert_not_empty assigns(:post).errors.full_messages
  end

  test 'parented post type rejects without parent' do
    sign_in users(:standard_user)

    try_create_post(post_type: post_types(:answer))

    assert_response(:found)
    assert_redirected_to root_path
    assert_not_nil flash[:danger]
    assert_nil assigns(:post).id
  end

  test 'create ensures community user is created' do
    user = users(:no_community_user)
    before = CommunityUser.where(user: user, community: communities(:sample)).count

    sign_in user
    try_create_post

    after = CommunityUser.where(user: user, community: communities(:sample)).count
    assert_equal before + 1, after, 'No CommunityUser record was created'
  end

  test 'should prevent deleted accounts from creating posts' do
    sign_in users(:deleted_account)
    try_create_post
    assert_redirected_to_sign_in
  end

  test 'should prevent deleted profiles from creating posts' do
    sign_in users(:deleted_profile)
    try_create_post
    assert_redirected_to_sign_in
  end

  private

  # Attempts to create a post
  # @param post_type [PostType]
  # @param category [Category, nil]
  # @param parent [Post, nil]
  # @param license [String]
  def try_create_post(post_type: post_types(:question),
                      category: categories(:main),
                      parent: nil,
                      license: licenses(:cc_by_sa))
    post :create, params: { post_type: post_type.id,
                            parent: parent&.id,
                            category: category&.id,
                            post: { post_type_id: post_type.id,
                                    title: sample.title,
                                    body_markdown: sample.body_markdown,
                                    category_id: category&.id,
                                    parent_id: parent&.id,
                                    tags_cache: sample.tags_cache,
                                    license_id: license.id } }
  end
end
