# frozen_string_literal: true

require "spec_helper"
require "decidim/api/test"

describe "Decidim::Api::QueryType" do
  include_context "with a graphql decidim component" do
    let(:component_fragment) do
      %(
      fragment fooComponent on Meetings {
        meeting(id: #{meeting.id}){
          acceptsNewComments
          address
          agenda {
            id
          }
          attachments {
            thumbnail
          }
          attendeesCount
          attendingOrganizations
          taxonomies {
            id
          }
          closed
          closedAt
          closingReport {
            translation(locale: "#{locale}")
          }
          commentsEnabled
          commentsEndTime
          commentsStartTime
          contributionCount
          customizeRegistrationEmail
          iframeAccessLevel
          iframeEmbedType
          videoUrl
          audioUrl
          comments {
            id
          }
          commentsHaveAlignment
          commentsHaveVotes
          contributionCount
          coordinates {
            latitude
            longitude
          }
          createdAt
          description {
            translation(locale: "#{locale}")
          }
          endTime
          followsCount
          hasComments
          id
          location {
            translation(locale: "#{locale}")
          }
          locationHints {
            translation(locale: "#{locale}")
          }
          privateMeeting
          proposalsFromMeeting {
            id
          }
          publicParticipants { id }
          publishedAt
          reference
          registrationForm {
            id
          }
          registrationsEnabled
          registrationTerms {
            translation(locale: "#{locale}")
          }
          registrationType
          registrationUrl
          registrationsEnabled
          remainingSlots
          services{
            description {
              translation(locale: "#{locale}")
            }
            title {
              translation(locale: "#{locale}")
            }
          }
          startTime
          title {
            translation(locale: "#{locale}")
          }
          totalCommentsCount
          transparent
          type
          updatedAt
          url
          userAllowedToComment
          withdrawn
        }
      }
)
    end
  end
  let(:component_type) { "Meetings" }

  let!(:current_component) { create(:meeting_component, participatory_space: participatory_process) }
  let!(:meeting) do
    create(:meeting, :published, :withdrawn, :not_official, :with_services, :closed_with_minutes,
           closing_visible:,
           component: current_component,
           taxonomies:,
           comments_end_time: Time.current.utc,
           comments_start_time: Time.current.utc + 1.day)
  end
  let!(:agenda) { create(:agenda, :with_agenda_items, meeting:) }
  let!(:invite) { create(:invite, :accepted, meeting:) }
  let(:closing_visible) { true }

  let(:meeting_single_result) do
    meeting.reload
    {
      "acceptsNewComments" => meeting.accepts_new_comments?,
      "address" => meeting.address,
      "agenda" => { "id" => meeting.agenda.id.to_s },
      "attachments" => [],
      "attendeesCount" => meeting.attendees_count,
      "attendingOrganizations" => meeting.attending_organizations,
      "taxonomies" => [{ "id" => meeting.taxonomies.first.id.to_s }],
      "closed" => true,
      "closedAt" => meeting.closed_at.to_time.iso8601,
      "closingReport" => closing_visible ? { "translation" => meeting.closing_report[locale] } : nil,
      "commentsEnabled" => meeting.comments_enabled,
      "commentsEndTime" => meeting.comments_end_time.to_time.iso8601,
      "videoUrl" => closing_visible ? meeting.video_url : nil,
      "audioUrl" => closing_visible ? meeting.audio_url : nil,
      "comments" => [],
      "commentsHaveAlignment" => meeting.comments_have_alignment?,
      "commentsHaveVotes" => meeting.comments_have_votes?,
      "commentsStartTime" => meeting.start_time.to_time.iso8601,
      "contributionCount" => meeting.contributions_count,
      "coordinates" => {
        "latitude" => meeting.latitude.to_f,
        "longitude" => meeting.longitude.to_f
      },
      "createdAt" => meeting.created_at.to_time.iso8601,
      "customizeRegistrationEmail" => meeting.customize_registration_email,
      "description" => { "translation" => meeting.description[locale] },
      "endTime" => meeting.end_time.to_time.iso8601,
      "followsCount" => meeting.follows_count,
      "hasComments" => meeting.comment_threads.size.positive?,
      "id" => meeting.id.to_s,
      "iframeAccessLevel" => meeting.iframe_access_level,
      "iframeEmbedType" => meeting.iframe_embed_type,
      "location" => { "translation" => meeting.location[locale] },
      "locationHints" => { "translation" => meeting.location_hints[locale] },
      "privateMeeting" => false,
      "proposalsFromMeeting" => [],
      "publicParticipants" => [],
      "publishedAt" => meeting.published_at.to_time.iso8601,
      "reference" => meeting.reference,
      "registrationForm" => { "id" => meeting.questionnaire.id.to_s },
      "registrationTerms" => { "translation" => meeting.registration_terms[locale] },
      "registrationType" => meeting.registration_type,
      "registrationUrl" => nil,
      "registrationsEnabled" => false,
      "remainingSlots" => 0,
      "services" => meeting.services.map do |s|
        {
          "description" => { "translation" => s.description[locale] },
          "title" => { "translation" => s.title[locale] }
        }
      end,
      "startTime" => meeting.start_time.to_time.iso8601,
      "title" => { "translation" => meeting.title[locale] },
      "totalCommentsCount" => meeting.comments_count,
      "transparent" => meeting.transparent?,
      "type" => "Decidim::Meetings::Meeting",
      "updatedAt" => meeting.updated_at.to_time.iso8601,
      "url" => Decidim::ResourceLocatorPresenter.new(meeting).url,
      "userAllowedToComment" => meeting.user_allowed_to_comment?(current_user),
      "withdrawn" => true
    }
  end

  let(:meeting_data) do
    {
      "__typename" => "Meetings",
      "id" => current_component.id.to_s,
      "name" => { "translation" => translated(current_component.name) },
      "meetings" => {
        "edges" => [
          {
            "node" => meeting_single_result
          }
        ]
      },
      "url" => Decidim::EngineRouter.main_proxy(current_component).root_url,
      "weight" => 0
    }
  end

  describe "commentable" do
    let(:component_fragment) { nil }

    let(:participatory_process_query) do
      %(
        commentable(id: "#{meeting.id}", type: "Decidim::Meetings::Meeting", locale: "en", toggleTranslations: false) {
          __typename
        }
      )
    end

    it "executes successfully" do
      expect { response }.not_to raise_error
    end

    it do
      expect(response).to eq({ "commentable" => { "__typename" => "Meeting" } })
    end
  end

  describe "valid connection query" do
    let(:component_fragment) do
      %(
      fragment fooComponent on Meetings {
        meetings{
          edges{
            node{
              acceptsNewComments
              address
              agenda {
                id
              }
              attachments {
                thumbnail
              }
              attendeesCount
              attendingOrganizations
              taxonomies {
                id
              }
              closed
              closedAt
              closingReport {
                translation(locale: "#{locale}")
              }
              commentsEnabled
              commentsEndTime
              commentsStartTime
              contributionCount
              customizeRegistrationEmail
              iframeAccessLevel
              iframeEmbedType
              videoUrl
              audioUrl
              comments {
                id
              }
              commentsHaveAlignment
              commentsHaveVotes
              contributionCount
              coordinates {
                latitude
                longitude
              }
              createdAt
              description {
                translation(locale: "#{locale}")
              }
              endTime
              followsCount
              hasComments
              id
              location {
                translation(locale: "#{locale}")
              }
              locationHints {
                translation(locale: "#{locale}")
              }
              privateMeeting
              proposalsFromMeeting {
                id
              }
              publicParticipants { id }
              publishedAt
              reference
              registrationForm {
                id
              }
              registrationsEnabled
              registrationTerms {
                translation(locale: "#{locale}")
              }
              registrationType
              registrationUrl
              registrationsEnabled
              remainingSlots
              services{
                description {
                  translation(locale: "#{locale}")
                }
                title {
                  translation(locale: "#{locale}")
                }
              }
              startTime
              title {
                translation(locale: "#{locale}")
              }
              totalCommentsCount
              transparent
              type
              updatedAt
              url
              userAllowedToComment
              withdrawn
            }
          }
        }
      }
)
    end

    it "executes successfully" do
      expect { response }.not_to raise_error
    end

    it { expect(response["participatoryProcess"]["components"].first).to include(meeting_data) }
  end

  describe "valid query" do
    it "executes successfully" do
      expect { response }.not_to raise_error
    end

    it { expect(response["participatoryProcess"]["components"].first["meeting"]).to eq(meeting_single_result) }

    context "when minutes is not visible" do
      let(:closing_visible) { false }

      it "executes successfully" do
        expect { response }.not_to raise_error
      end

      it { expect(response["participatoryProcess"]["components"].first["meeting"]).to eq(meeting_single_result) }
    end
  end

  include_examples "with resource visibility" do
    let(:component_factory) { :meeting_component }
    let(:lookout_key) { "meeting" }
    let(:query_result) { meeting_single_result }
  end
end
