module JamRuby
  class EmailBatchNewMusician < EmailBatchPeriodic

    BATCH_SIZE = 500

    SINCE_DAYS = 14

    VAR_MUSICIAN_COUNT = "@MUSICIAN_COUNT"
    VAR_MUSICIAN_TABLE = "@MUSICIAN_TABLE"

    TMP_NEW = 'tmp_new_musicians'
    TMP_RECEIVE = 'tmp_receivers'
    TMP_PAIRS = 'tmp_receivers_new_musicians'

    def self.subject
      "New musicians with good Internet connections to you have joined JamKazam!"
    end

    # inserts eligible sessions to temp table
    def _fetch_new_musicians
      ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_NEW}")
      sql =<<SQL
SELECT 
  users.id AS new_user_id, 
  users.last_jam_locidispid AS last_jam_locidispid,
  users.created_at AS new_created_at
INTO TEMP TABLE #{TMP_NEW} 
FROM users
WHERE
    users.musician = 't' AND
    users.last_jam_locidispid IS NOT NULL AND
    users.created_at > '#{time_since_last_batch(SINCE_DAYS)}' AND
    users.created_at <= '#{self.created_at}'
SQL
      ActiveRecord::Base.connection.execute(sql)
    end

    # inserts eligible sessions to temp table
    def _fetch_eligible_receivers
      ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_RECEIVE}")
      sql =<<SQL
SELECT 
  rr.id AS receiver_id,
  rr.created_at AS receiver_created_at
INTO TEMP TABLE #{TMP_RECEIVE}
FROM users rr
FULL OUTER JOIN #{TMP_NEW} ON #{TMP_NEW}.new_user_id = rr.id
WHERE
  rr.musician = 't' AND
  rr.subscribe_email = 't' AND
  rr.last_jam_locidispid IS NOT NULL AND 
  (#{TMP_NEW}.new_user_id IS NULL OR rr.id IS NULL)
SQL
      ActiveRecord::Base.connection.execute(sql)
    end

    def _fetch_pairs
      ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS #{TMP_PAIRS}")
      # load eligible recipients into tmp table
      sql =<<SQL
SELECT 
    #{TMP_NEW}.new_user_id, 
    receivers.id AS receiver_id,
    scores.score AS latency
INTO TEMP TABLE #{TMP_PAIRS}
FROM scores
INNER JOIN users AS receivers ON receivers.id = scores.a_userid
INNER JOIN #{TMP_NEW} ON #{TMP_NEW}.new_user_id = scores.b_userid
WHERE 
    scores.score < #{Score::MAX_YELLOW_LATENCY} AND
    receivers.id IN (
      SELECT receiver_id
      FROM #{TMP_RECEIVE}
    )
SQL
      ActiveRecord::Base.connection.execute(sql)
    end

    def fetch_recipients(per_page=500)
      objs = []
      # load new musicians into tmp table
      self._fetch_new_musicians

      # load email receivers into tmp table
      self._fetch_eligible_receivers

      # load receivers/musicians pairs into tmp table
      self._fetch_pairs

      countsql = "SELECT COUNT(DISTINCT receiver_id) AS num FROM #{TMP_PAIRS}"
      rr = ActiveRecord::Base.connection.execute(countsql)
      num_pair = 0 < rr.count ? rr[0]['num'].to_i : 0

      loops = (num_pair / per_page) + (num_pair % per_page) - 1
      0.upto(loops) do |nn|
        offset = nn * per_page
        sql =<<SQL
SELECT DISTINCT receiver_id 
FROM #{TMP_PAIRS} 
ORDER BY receiver_id ASC
LIMIT #{per_page}
OFFSET #{offset}
SQL
        ActiveRecord::Base.connection.execute(sql).each do |result|
          receiver = User.find_by_id(result['receiver_id'])
          new_musicians = User.select("users.*, #{TMP_PAIRS}.latency")
            .joins("INNER JOIN #{TMP_PAIRS} ON #{TMP_PAIRS}.new_user_id = users.id")
            .where(["#{TMP_PAIRS}.receiver_id = ?", receiver.id])
            .includes(:instruments)
          block_given? ? yield(receiver, new_musicians) : objs << [receiver, new_musicians]
        end
      end
      objs
    end

    def deliver_batch_sets!
      self.opt_in_count = 0
      self.fetch_recipients do |user, new_musicians|
        self.opt_in_count += 1
        bset = EmailBatchSet.new_musician_set(self, user, new_musicians)
        UserMailer.new_musicians(user, new_musicians).deliver_now
      end
      self.sent_count = self.opt_in_count
      self.save
      self.did_batch_run!
    end

    def self.send_new_musician_batch
      oo = self.create
      oo.deliver_batch
      oo
    end

  end
end
