# frozen_string_literal: true

module Decidim
  module ActionDelegator
    class Participant < ApplicationRecord
      self.table_name = "decidim_action_delegator_participants"

      belongs_to :setting,
                 foreign_key: "decidim_action_delegator_setting_id",
                 class_name: "Decidim::ActionDelegator::Setting"

      belongs_to :ponderation,
                 foreign_key: "decidim_action_delegator_ponderation_id",
                 class_name: "Decidim::ActionDelegator::Ponderation",
                 optional: true

      belongs_to :decidim_user,
                 class_name: "Decidim::User",
                 optional: true

      delegate :consultation, to: :setting
      delegate :organization, to: :setting

      validates :setting, presence: true
      validates :decidim_user, uniqueness: { scope: :setting }, if: -> { decidim_user.present? }
      validates :email, uniqueness: { scope: :setting }, if: -> { email.present? }
      validates :phone, uniqueness: { scope: :setting }, if: -> { phone.present? }

      # sets the decidim user if found
      before_save :set_decidim_user

      # prevents destroy if has voted
      before_destroy { |record| throw(:abort) if record.voted? }

      def user
        @user ||= decidim_user || user_from_metadata
      end

      def user_from_metadata
        @user_from_metadata ||= if setting.email_required?
                                  Decidim::User.find_by(email: email, organization: setting.organization)
                                else
                                  Decidim::Authorization.find_by(unique_id: uniq_ids)&.user
                                end
      end

      def uniq_ids
        @uniq_ids ||= Participant.verifier_ids(Participant.phone_combinations(["#{phone}-#{organization.id}"]))
      end

      def self.verifier_ids(seeds)
        seeds.map { |seed| Digest::MD5.hexdigest("#{seed}-#{Digest::MD5.hexdigest(Rails.application.secrets.secret_key_base)}") }
      end

      def self.phone_combinations(phones)
        phones.map do |phone|
          phone_prefixes.map do |prefix|
            [
              "#{prefix}#{phone}",
              phone.delete_prefix(prefix)
            ]
          end
        end.flatten.uniq
      end

      def self.phone_prefixes
        prefixes = [""]
        prefixes += ActionDelegator.phone_prefixes if ActionDelegator.phone_prefixes.respond_to?(:map)
        prefixes
      end

      def user_name
        user&.name
      end

      def last_login
        user&.last_sign_in_at
      end

      def ponderation_title
        ponderation&.title
      end

      # checks if the user has voted in the setting's consultation
      def voted?
        return false if user.blank?

        @voted ||= if Decidim::Consultations::Vote
                      .joins(question: :consultation)
                      .where(decidim_consultations_questions: {
                               decidim_consultation_id: setting.consultation.id
                             }, author: user).any?
                     true
                   else
                     false
                   end
      end

      private

      def set_decidim_user
        self.decidim_user = user_from_metadata if decidim_user.blank?
      end
    end
  end
end