# frozen_string_literal: true

module Lists
  class RepositoriesService < BaseService
    private

    def fetch_records
      user_assignments = @raw_data.joins(:user_assignments).where(user_assignments: { team_id: @user.current_team.id }).select(:assignable_id, :user_id)
      user_group_assignments = @raw_data.joins(user_group_assignments: { user_group: :user_group_memberships })
                                        .where(user_group_assignments: { team_id: @user.current_team.id })
                                        .select('user_group_assignments.assignable_id, user_group_memberships.user_id')
      team_assignments = @raw_data.joins(team_assignments: { team: :user_assignments })
                                  .where(team_assignments: { team_id: @user.current_team.id })
                                  .select('team_assignments.assignable_id, user_assignments.user_id')

      @records = @raw_data.joins('LEFT OUTER JOIN users AS creators ' \
                                 'ON repositories.created_by_id = creators.id')
                          .joins('LEFT OUTER JOIN users AS archivers ' \
                                 'ON repositories.archived_by_id = archivers.id')
                          .joins("LEFT OUTER JOIN (#{user_assignments.to_sql} UNION #{team_assignments.to_sql} UNION #{user_group_assignments.to_sql})
                                 all_assigned_users ON all_assigned_users.assignable_id = repositories.id")
                          .joins('INNER JOIN teams AS teams_repositories ON teams_repositories.id = repositories.team_id')
                          .select('repositories.*')
                          .select('MAX(teams_repositories.name) AS team_name')
                          .select('MAX(creators.full_name) AS created_by_user')
                          .select('MAX(archivers.full_name) AS archived_by_user')
                          .select('COUNT(DISTINCT all_assigned_users.user_id) AS "assigned_users_count"')
                          .select(shared_sql_select)
                          .preload(:team_assignments, :user_group_assignments, user_assignments: %i(user user_role))
                          .group('repositories.id')

      view_mode = @params[:view_mode] || 'active'

      @records = @records.archived if view_mode == 'archived'
      @records = @records.active if view_mode == 'active'
    end

    def filter_records
      return unless @params[:search]

      @records = @records.where_attributes_like(
        [
          'repositories.name',
          'teams_repositories.name',
          'creators.full_name',
          'archivers.full_name'
        ],
        @params[:search]
      )
    end

    def sortable_columns
      @sortable_columns ||= {
        name: 'repositories.name',
        team: 'team_name',
        created_by: 'created_by_user',
        created_at: 'repositories.created_at',
        archived_on: 'repositories.archived_on',
        archived_by: 'archived_by_user',
        nr_of_rows: 'repository_rows_count',
        code: 'repositories.id',
        shared_label: 'shared',
        assigned_users: 'assigned_users_count'
      }
    end

    def shared_sql_select
      shared_write_value = Repository.permission_levels['shared_write']
      not_shared_value = Repository.permission_levels['not_shared']
      team_id = @user.current_team.id

      case_statement = <<-SQL.squish
        CASE
          WHEN repositories.team_id = :team_id AND (repositories.permission_level NOT IN (:not_shared_value)
            OR EXISTS (
            SELECT 1 FROM team_shared_objects
            WHERE team_shared_objects.shared_object_id = repositories.id
              AND team_shared_objects.shared_object_type = 'RepositoryBase'
              AND team_shared_objects.team_id != :team_id
            )) THEN 1
          WHEN repositories.team_id != :team_id AND repositories.permission_level NOT IN (:not_shared_value)
            OR EXISTS (
            SELECT 1 FROM team_shared_objects
            WHERE team_shared_objects.shared_object_id = repositories.id
              AND team_shared_objects.shared_object_type = 'RepositoryBase'
              AND team_shared_objects.team_id = :team_id
          ) THEN
              CASE
                WHEN repositories.permission_level IN (:shared_write_value)
                  OR EXISTS (
                    SELECT 1 FROM team_shared_objects
                    WHERE team_shared_objects.shared_object_id = repositories.id
                      AND team_shared_objects.shared_object_type = 'RepositoryBase'
                      AND team_shared_objects.permission_level = :shared_write_value
                      AND team_shared_objects.team_id = :team_id
                  ) THEN 2
                ELSE 3
              END
          ELSE 4
        END as shared
      SQL

      ActiveRecord::Base.sanitize_sql_array(
        [case_statement, { team_id:, not_shared_value:, shared_write_value: }]
      )
    end
  end
end
