# frozen_string_literal: true

require "spec_helper"

module Decidim
  describe Debates::DownloadYourDataDebateSerializer do
    subject do
      described_class.new(debate)
    end

    let!(:debate) { create(:debate) }
    let!(:taxonomies) { create_list(:taxonomy, 2, :with_parent, organization: component.organization) }
    let(:participatory_process) { component.participatory_space }
    let(:component) { debate.component }
    let(:new_debate) { described_class.new(debate) }
    let(:serialized_taxonomies) do
      { ids: taxonomies.pluck(:id) }.merge(taxonomies.to_h { |t| [t.id, t.name] })
    end

    before do
      debate.update!(taxonomies:)
    end

    describe "#serialize" do
      let(:serialized) { subject.serialize }

      it "serializes the id" do
        expect(serialized).to include(id: debate.id)
      end

      it "serializes the taxonomies" do
        expect(serialized[:taxonomies]).to eq(serialized_taxonomies)
      end

      describe "author" do
        context "when it is a user" do
          let(:author) { create(:user, name: "John Doe", organization: component.organization) }
          let(:component) { create(:debates_component) }
          let!(:debate) { create(:debate, component:, author:) }

          it "does not serialize the user name" do
            expect(serialized).not_to include(name: "John Doe")
          end

          it "does not serialize the link to its profile" do
            expect(serialized).not_to include(author: { url: profile_url(debate.author.nickname) })
          end
        end
      end

      it "serializes the title" do
        expect(serialized).to include(title: debate.title)
      end

      it "serializes the description" do
        expect(serialized).to include(description: debate.description)
      end

      it "serializes the start time" do
        expect(serialized).to include(start_time: debate.start_time)
      end

      it "serializes the end time" do
        expect(serialized).to include(end_time: debate.end_time)
      end

      it "serializes the information updates" do
        expect(serialized).to include(information_updates: debate.information_updates)
      end

      it "serializes the participatory space" do
        expect(serialized[:participatory_space]).to include(id: participatory_process.id)
        expect(serialized[:participatory_space][:url]).to include("http", participatory_process.slug)
      end

      it "serializes the component" do
        expect(serialized[:component]).to include(id: debate.component.id)
      end

      it "serializes the reference" do
        expect(serialized).to include(reference: debate.reference)
      end

      it "serializes the comments" do
        expect(serialized).to include(comments: debate.comments_count)
      end

      it "serializes the number of followers" do
        expect(serialized).to include(follows_count: debate.follows_count)
      end

      it "serializes the url" do
        expect(serialized[:url]).to include("http", debate.id.to_s)
      end

      it "serializes the last comment at" do
        expect(serialized).to include(last_comment_at: debate.last_comment_at)
      end

      it "serializes the comments enabled" do
        expect(serialized).to include(comments_enabled: debate.comments_enabled)
      end

      it "includes the created at" do
        expect(serialized).to include(created_at: debate.created_at)
      end

      it "includes the updated at" do
        expect(serialized).to include(updated_at: debate.updated_at)
      end

      it "serializes the likes" do
        expect(serialized).to include(likes_count: debate.likes_count)
      end

      describe "conclusions and closed at" do
        it "does not serializes the conclusion" do
          expect(serialized[:conclusions]).to be_nil
        end

        it "does not serializes the closed at" do
          expect(serialized[:closed_at]).to be_nil
        end

        context "when the debate is closed" do
          let!(:debate) { create(:debate, :closed) }

          it "serializes the conclusion" do
            expect(serialized).to include(conclusions: debate.conclusions)
          end

          it "serializes the closed at" do
            expect(serialized).to include(closed_at: debate.closed_at)
          end
        end

        context "when the debate is not closed" do
          let!(:debate) { create(:debate, closed_at: nil) }

          it "does not serialize the conclusion" do
            expect(serialized[:conclusions]).to be_nil
          end

          it "does not serialize the closed at" do
            expect(serialized[:closed_at]).to be_nil
          end
        end
      end

      context "when there is a last comment" do
        let(:last_comment_by) { create(:user, name: "User") }
        let(:debate) { create(:debate, last_comment_by:) }

        it "serializes the last comment by fields" do
          expect(serialized[:last_comment_by]).to eq(
            id: last_comment_by.id,
            name: "User",
            url: profile_url(last_comment_by.nickname)
          )
        end

        context "when the last comment is from a deleted user" do
          let(:last_comment_by) { create(:user, :deleted) }
          let(:debate) { create(:debate, last_comment_by:) }

          it "does not serialize the fields" do
            expect(serialized[:last_comment_by]).to eq({})
          end
        end
      end

      context "when there is no last comment" do
        let(:debate) { create(:debate, last_comment_by: nil) }

        it "returns no values" do
          expect(serialized[:last_comment_by]).to eq({})
        end
      end
    end

    def profile_url(nickname)
      Decidim::Core::Engine.routes.url_helpers.profile_url(nickname, host:, port: Capybara.server_port)
    end

    def host
      debate.organization.host
    end
  end
end
