# frozen_string_literal: true

RSpec.describe "AI Bot - Homepage", type: :system do
  let(:topic_page) { PageObjects::Pages::Topic.new }
  let(:composer) { PageObjects::Components::Composer.new }
  let(:ai_pm_homepage) { PageObjects::Components::AiPmHomepage.new }
  let(:header) { PageObjects::Pages::DiscourseAi::Header.new }
  let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new }
  let(:header_dropdown) { PageObjects::Components::NavigationMenu::HeaderDropdown.new }
  let(:dialog) { PageObjects::Components::Dialog.new }

  fab!(:user) { Fabricate(:user, refresh_auto_groups: true) }
  fab!(:user_2) { Fabricate(:user, refresh_auto_groups: true) }

  fab!(:claude_2) do
    Fabricate(
      :llm_model,
      provider: "anthropic",
      url: "https://api.anthropic.com/v1/messages",
      name: "claude-2",
      display_name: "Claude 2",
    )
  end
  fab!(:claude_2_dup) do
    Fabricate(
      :llm_model,
      provider: "anthropic",
      url: "https://api.anthropic.com/v1/messages",
      name: "claude-2",
      display_name: "Duplicate",
    )
  end
  fab!(:bot_user) do
    toggle_enabled_bots(bots: [claude_2, claude_2_dup])
    SiteSetting.ai_bot_enabled = true
    claude_2.reload.user
  end
  fab!(:bot) do
    persona =
      AiPersona
        .find(DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::General])
        .class_instance
        .new
    DiscourseAi::Personas::Bot.as(bot_user, persona: persona)
  end

  fab!(:pm) do
    Fabricate(
      :private_message_topic,
      title: "This is my special PM",
      user: user,
      last_posted_at: Time.zone.now,
      topic_allowed_users: [
        Fabricate.build(:topic_allowed_user, user: user),
        Fabricate.build(:topic_allowed_user, user: bot_user),
      ],
    )
  end
  fab!(:first_post) do
    Fabricate(:post, topic: pm, user: user, post_number: 1, raw: "This is a reply by the user")
  end
  fab!(:second_post) do
    Fabricate(:post, topic: pm, user: bot_user, post_number: 2, raw: "This is a bot reply")
  end
  fab!(:third_post) do
    Fabricate(
      :post,
      topic: pm,
      user: user,
      post_number: 3,
      raw: "This is a second reply by the user",
    )
  end
  fab!(:topic_user) { Fabricate(:topic_user, topic: pm, user: user) }
  fab!(:topic_bot_user) { Fabricate(:topic_user, topic: pm, user: bot_user) }

  fab!(:persona) do
    persona =
      AiPersona.create!(
        name: "Test Persona",
        description: "A test persona",
        allowed_group_ids: [Group::AUTO_GROUPS[:trust_level_0]],
        enabled: true,
        system_prompt: "You are a helpful bot",
      )

    persona.create_user!
    persona.update!(
      default_llm_id: claude_2.id,
      allow_chat_channel_mentions: true,
      allow_topic_mentions: true,
    )
    persona
  end

  before do
    pm.custom_fields[DiscourseAi::AiBot::TOPIC_AI_BOT_PM_FIELD] = "t"
    pm.save!

    SiteSetting.ai_bot_enable_dedicated_ux = true
    SiteSetting.ai_bot_enabled = true
    SiteSetting.navigation_menu = "sidebar"
    Jobs.run_immediately!
    SiteSetting.ai_bot_allowed_groups = "#{Group::AUTO_GROUPS[:trust_level_0]}"
    sign_in(user)
  end

  %w[enabled disabled].each do |value|
    before { SiteSetting.glimmer_post_stream_mode = value }

    context "when glimmer_post_stream_mode=#{value}" do
      context "when mobile", mobile: true do
        it "allows navigating from AI conversation to regular topic, and loads new post stream" do
          regular_topic = Fabricate(:topic)
          regular_post = Fabricate(:post, topic: regular_topic)

          post_url = Topic.relative_url(regular_topic.id, regular_topic.slug)
          post_with_link =
            Fabricate(
              :post,
              topic: pm,
              user: user,
              post_number: 4,
              raw: "This is a second reply by the user [link](#{post_url})",
            )

          topic_page.visit_topic(pm)
          page.find(
            "article[data-post-id='#{post_with_link.id}'] .cooked a[href='#{post_url}']",
          ).click

          try_until_success do
            expect(topic_page.current_topic).to eq(regular_topic)
            expect(page).to have_css("article[data-post-id='#{regular_post.id}']")
          end
        end
      end

      context "when `ai_bot_enable_dedicated_ux` is enabled" do
        it "allows uploading files to a new conversation" do
          ai_pm_homepage.visit
          expect(ai_pm_homepage).to have_homepage

          file_path_1 = file_from_fixtures("logo.png", "images").path
          file_path_2 = file_from_fixtures("logo.jpg", "images").path

          attach_file([file_path_1, file_path_2]) do
            find(".ai-bot-upload-btn", visible: true).click
          end

          expect(page).to have_css(".ai-bot-upload", count: 2)

          ai_pm_homepage.input.fill_in(with: "Here are two image attachments")

          responses = ["hello user", "topic title"]
          DiscourseAi::Completions::Llm.with_prepared_responses(responses) do
            ai_pm_homepage.submit
            expect(topic_page).to have_content("Here are two image attachments")
            expect(page).to have_css(".cooked img", count: 2)
          end

          find(".ai-new-question-button").click
          expect(ai_pm_homepage).to have_homepage
          expect(page).to have_no_css(".ai-bot-upload")
        end

        it "allows removing an upload before submission" do
          ai_pm_homepage.visit
          expect(ai_pm_homepage).to have_homepage

          file_path = file_from_fixtures("logo.png", "images").path
          attach_file([file_path]) { find(".ai-bot-upload-btn", visible: true).click }
          expect(page).to have_css(".ai-bot-upload", count: 1)

          find(".ai-bot-upload__remove").click

          expect(page).to have_no_css(".ai-bot-upload")

          ai_pm_homepage.input.fill_in(with: "Message without attachments")

          responses = ["hello user", "topic title"]
          DiscourseAi::Completions::Llm.with_prepared_responses(responses) do
            ai_pm_homepage.submit
            expect(topic_page).to have_content("Message without attachments")
            expect(page).to have_no_css(".cooked img")
          end
        end

        it "renders landing page on bot click" do
          visit "/"
          header.click_bot_button
          expect(ai_pm_homepage).to have_homepage
          expect(sidebar).to be_visible
        end

        it "displays error when message is too short" do
          visit "/"
          header.click_bot_button

          ai_pm_homepage.input.fill_in(with: "a")
          ai_pm_homepage.submit
          expect(ai_pm_homepage).to have_too_short_dialog
          dialog.click_yes
          expect(composer).to be_closed
        end

        it "hides default content in the sidebar" do
          visit "/"
          header.click_bot_button

          expect(ai_pm_homepage).to have_homepage
          expect(sidebar).to have_no_tags_section
          expect(sidebar).to have_no_section("categories")
          expect(sidebar).to have_no_section("messages")
          expect(sidebar).to have_no_section("chat-dms")
          expect(sidebar).to have_no_section("chat-channels")
          expect(sidebar).to have_no_section("user-threads")
        end

        it "shows the bot conversation in the sidebar" do
          visit "/"
          header.click_bot_button

          expect(ai_pm_homepage).to have_homepage
          expect(sidebar).to have_section("Today")
          expect(sidebar).to have_section_link(pm.title)
        end

        it "shows empty state when no PMs exist" do
          pm.destroy!

          visit "/"
          header.click_bot_button

          expect(page).to have_css(".sidebar-section .ai-bot-sidebar-empty-state", visible: true)
        end

        it "doesn't show empty state when a PM exists" do
          visit "/"
          header.click_bot_button

          expect(page).to have_no_css(".sidebar-section .ai-bot-sidebar-empty-state")
        end

        it "displays last_7_days label in the sidebar" do
          pm.update!(last_posted_at: Time.zone.now - 5.days)
          visit "/"
          header.click_bot_button

          expect(ai_pm_homepage).to have_homepage
          expect(sidebar).to have_section("Last 7 days")
        end

        it "displays last_30_days label in the sidebar" do
          pm.update!(last_posted_at: Time.zone.now - 28.days)
          visit "/"
          header.click_bot_button

          expect(ai_pm_homepage).to have_homepage
          expect(sidebar).to have_section("Last 30 days")
        end

        it "displays month and year label in the sidebar for older conversations" do
          pm.update!(last_posted_at: "2024-04-10 15:39:11.406192000 +00:00")
          visit "/"
          header.click_bot_button

          expect(ai_pm_homepage).to have_homepage
          expect(sidebar).to have_section("2024-3")
        end

        it "navigates to the bot conversation when clicked" do
          visit "/"
          header.click_bot_button

          expect(ai_pm_homepage).to have_homepage
          ai_pm_homepage.click_fist_sidebar_conversation
          expect(topic_page).to have_topic_title(pm.title)
        end

        it "displays the shuffle icon when on homepage or bot PM" do
          visit "/"
          expect(header).to have_icon_in_bot_button(icon: "robot")
          header.click_bot_button

          expect(header).to have_icon_in_bot_button(icon: "shuffle")

          # Go to a PM and assert that the icon is still shuffle
          ai_pm_homepage.click_fist_sidebar_conversation
          expect(header).to have_icon_in_bot_button(icon: "shuffle")

          # Go back home and assert that the icon is now robot again
          header.click_bot_button
          expect(header).to have_icon_in_bot_button(icon: "robot")
        end

        it "displays 'new question' button on homepage and topic page" do
          topic_page.visit_topic(pm)
          expect(ai_pm_homepage).to have_new_question_button

          ai_pm_homepage.visit
          expect(ai_pm_homepage).to have_new_question_button
        end

        it "redirect to the homepage when 'new question' is clicked" do
          topic_page.visit_topic(pm)
          expect(sidebar).to be_visible
          ai_pm_homepage.click_new_question_button
          expect(ai_pm_homepage).to have_homepage
        end

        it "can send a new message to the bot" do
          topic_page.visit_topic(pm)
          topic_page.click_reply_button
          expect(composer).to be_opened

          composer.fill_in(with: "Hello bot replying to you")
          composer.submit
          expect(page).to have_content("Hello bot replying to you")
        end

        it "does not render custom sidebar on non-authored bot pms" do
          # Include user_2 in the PM by creating a new post and topic_allowed_user association
          Fabricate(:post, topic: pm, user: user_2, post_number: 4)
          Fabricate(:topic_allowed_user, topic: pm, user: user_2)
          sign_in(user_2)

          topic_page.visit_topic(pm)

          expect(sidebar).to be_visible
          expect(sidebar).to have_no_section("ai-conversations-history")
          expect(sidebar).to have_no_css("button.ai-new-question-button")
        end

        it "does not include non-authored bot pms in sidebar" do
          # Include user_2 in the PM by creating a new post and topic_allowed_user association
          Fabricate(:post, topic: pm, user: user_2, post_number: 4)
          Fabricate(:topic_allowed_user, topic: pm, user: user_2)
          sign_in(user_2)
          visit "/"
          header.click_bot_button
          expect(ai_pm_homepage).to have_homepage
          expect(sidebar).to have_no_section_link(pm.title)
        end

        it "Allows choosing persona and LLM" do
          ai_pm_homepage.visit

          ai_pm_homepage.llm_selector.expand
          ai_pm_homepage.llm_selector.select_row_by_name(claude_2_dup.display_name)
          ai_pm_homepage.llm_selector.collapse

          # confirm memory works for llm selection
          ai_pm_homepage.visit
          expect(ai_pm_homepage.llm_selector).to have_selected_name(claude_2_dup.display_name)
        end

        it "does not render back to forum link" do
          ai_pm_homepage.visit
          expect(ai_pm_homepage).to have_no_sidebar_back_link
        end

        context "with hamburger menu" do
          before { SiteSetting.navigation_menu = "header dropdown" }
          it "keeps robot icon in the header and doesn't display sidebar back link" do
            visit "/"
            expect(header).to have_icon_in_bot_button(icon: "robot")
            header.click_bot_button
            expect(ai_pm_homepage).to have_homepage
            expect(header).to have_icon_in_bot_button(icon: "robot")
            expect(ai_pm_homepage).to have_no_sidebar_back_link
          end

          it "still renders the sidebar" do
            visit "/"
            header.click_bot_button
            expect(ai_pm_homepage).to have_homepage
            expect(sidebar).to be_visible
            expect(header_dropdown).to be_visible
          end
        end
      end

      context "when `ai_bot_enable_dedicated_ux` is disabled" do
        before { SiteSetting.ai_bot_enable_dedicated_ux = false }

        it "opens composer on bot click" do
          visit "/"
          header.click_bot_button

          expect(ai_pm_homepage).to have_no_homepage
          expect(composer).to be_opened
        end

        it "does not render sidebar when navigation menu is set to header on pm" do
          SiteSetting.navigation_menu = "header dropdown"
          topic_page.visit_topic(pm)

          expect(ai_pm_homepage).to have_no_homepage
          expect(sidebar).to be_not_visible
          expect(header_dropdown).to be_visible
        end

        it "shows default content in the sidebar" do
          topic_page.visit_topic(pm)

          expect(sidebar).to have_section("categories")
          expect(sidebar).to have_section("messages")
          expect(sidebar).to have_section("chat-dms")
          expect(sidebar).to have_no_css("button.ai-new-question-button")
        end
      end

      context "with header dropdown on mobile", mobile: true do
        before { SiteSetting.navigation_menu = "header dropdown" }

        it "displays the new question button in the menu when viewing a PM" do
          ai_pm_homepage.visit
          header_dropdown.open
          expect(ai_pm_homepage).to have_new_question_button

          topic_page.visit_topic(pm)
          header_dropdown.open
          ai_pm_homepage.click_new_question_button

          # Hamburger sidebar is closed
          expect(header_dropdown).to have_no_dropdown_visible
        end
      end
    end
  end
end
