require "mysql2"
require File.expand_path(File.dirname(__FILE__) + "/base.rb")
require File.expand_path(File.dirname(__FILE__) + "/drupal.rb")

class ImportScripts::DrupalQA < ImportScripts::Drupal

  def categories_query
    result = @client.query("SELECT n.nid, GROUP_CONCAT(ti.tid) AS tids
                            FROM node AS n
                            INNER JOIN taxonomy_index AS ti ON ti.nid = n.nid
                            WHERE n.type = 'question'
                              AND n.status = 1
                            GROUP BY n.nid")

    categories = {}
    result.each do |r|
      tids = r['tids']
      if tids.present?
        tids = tids.split(',')
        categories[tids[0].to_i] = true
      end
    end

    @client.query("SELECT tid, name, description FROM taxonomy_term_data WHERE tid IN (#{categories.keys.join(',')})")
  end

  def create_forum_topics

    puts '', "creating forum topics"

    total_count = @client.query("
        SELECT COUNT(*) count
          FROM node n
         WHERE n.type = 'question'
           AND n.status = 1;").first['count']

    batch_size = 1000

    batches(batch_size) do |offset|
      results = @client.query("
        SELECT n.nid,
               n.title,
               GROUP_CONCAT(t.tid) AS tid,
               n.uid,
               n.created,
               f.body_value AS body
        FROM node AS n
          LEFT OUTER JOIN taxonomy_index AS t on t.nid = n.nid
          INNER JOIN field_data_body AS f ON f.entity_id = n.nid
        WHERE n.type = 'question'
          AND n.status = 1
        GROUP BY n.nid, n.title, n.uid, n.created, f.body_value
        LIMIT #{batch_size}
        OFFSET #{offset}
      ", cache_rows: false);

      break if results.size < 1

      next if all_records_exist? :posts, results.map {|p| "nid:#{p['nid']}"}

      create_posts(results, total: total_count, offset: offset) do |row|
        {
          id: "nid:#{row['nid']}",
          user_id: user_id_from_imported_user_id(row['uid']) || -1,
          category: category_id_from_imported_category_id((row['tid'] || '').split(',')[0]),
          raw: row['body'],
          created_at: Time.zone.at(row['created']),
          pinned_at: nil,
          title: row['title'].try(:strip)
        }
      end
    end
  end

  def create_direct_replies
    puts '', "creating replies in topics"

    total_count = @client.query("
        SELECT COUNT(*) count
          FROM node n
         WHERE n.type = 'answer'
           AND n.status = 1;").first['count']

    batch_size = 1000

    batches(batch_size) do |offset|

      results = @client.query("
        SELECT n.nid AS cid,
               q.field_answer_question_nid AS nid,
               n.uid,
               n.created,
               f.body_value AS body
        FROM node AS n
          INNER JOIN field_data_field_answer_question AS q ON q.entity_id = n.nid
          INNER JOIN field_data_body AS f ON f.entity_id = n.nid
        WHERE n.status = 1
          AND n.type = 'answer'
        LIMIT #{batch_size}
        OFFSET #{offset}
      ", cache_rows: false)

      break if results.size < 1

      next if all_records_exist? :posts, results.map {|p| "cid:#{p['cid']}"}

      create_posts(results, total: total_count, offset: offset) do |row|
        topic_mapping = topic_lookup_from_imported_post_id("nid:#{row['nid']}")
        if topic_mapping && topic_id = topic_mapping[:topic_id]
          h = {
            id: "cid:#{row['cid']}",
            topic_id: topic_id,
            user_id: user_id_from_imported_user_id(row['uid']) || -1,
            raw: row['body'],
            created_at: Time.zone.at(row['created']),
          }
          h
        else
          puts "No topic found for answer #{row['cid']}"
          nil
        end
      end
    end
  end

  def create_nested_replies
    puts '', "creating nested replies to posts in topics"

    total_count = @client.query("
        SELECT COUNT(c.cid) count
          FROM node n
        INNER JOIN comment AS c ON n.nid = c.nid
        WHERE n.type = 'question'
           AND n.status = 1;").first['count']

    batch_size = 1000

    batches(batch_size) do |offset|

      # WARNING: If there are more than 1000000 this might have to be revisited
      results = @client.query("
        SELECT (c.cid + 1000000) as cid,
               c.nid,
               c.uid,
               c.created,
               cb.comment_body_value AS body
        FROM node AS n
          INNER JOIN comment AS c ON c.nid = n.nid
          INNER JOIN field_data_comment_body AS cb ON cb.entity_id = c.cid
        WHERE n.status = 1
          AND n.type = 'question'
        LIMIT #{batch_size}
        OFFSET #{offset}
      ", cache_rows: false)

      break if results.size < 1

      next if all_records_exist? :posts, results.map {|p| "cid:#{p['cid']}"}

      create_posts(results, total: total_count, offset: offset) do |row|
        topic_mapping = topic_lookup_from_imported_post_id("nid:#{row['nid']}")
        if topic_mapping && topic_id = topic_mapping[:topic_id]
          h = {
            id: "cid:#{row['cid']}",
            topic_id: topic_id,
            user_id: user_id_from_imported_user_id(row['uid']) || -1,
            raw: row['body'],
            created_at: Time.zone.at(row['created']),
          }
          h
        else
          puts "No topic found for comment #{row['cid']}"
          nil
        end
      end
    end

    puts '', "creating nested replies to answers in topics"

    total_count = @client.query("
        SELECT COUNT(c.cid) count
          FROM node n
        INNER JOIN comment AS c ON n.nid = c.nid
        WHERE n.type = 'answer'
           AND n.status = 1;").first['count']

    batch_size = 1000

    batches(batch_size) do |offset|

      # WARNING: If there are more than 1000000 this might have to be revisited
      results = @client.query("
        SELECT (c.cid + 1000000) as cid,
               q.field_answer_question_nid AS nid,
               c.uid,
               c.created,
               cb.comment_body_value AS body
        FROM node AS n
          INNER JOIN field_data_field_answer_question AS q ON q.entity_id = n.nid
          INNER JOIN comment AS c ON c.nid = n.nid
          INNER JOIN field_data_comment_body AS cb ON cb.entity_id = c.cid
        WHERE n.status = 1
          AND n.type = 'answer'
        LIMIT #{batch_size}
        OFFSET #{offset}
      ", cache_rows: false)

      break if results.size < 1

      next if all_records_exist? :posts, results.map {|p| "cid:#{p['cid']}"}

      create_posts(results, total: total_count, offset: offset) do |row|
        topic_mapping = topic_lookup_from_imported_post_id("nid:#{row['nid']}")
        if topic_mapping && topic_id = topic_mapping[:topic_id]
          h = {
            id: "cid:#{row['cid']}",
            topic_id: topic_id,
            user_id: user_id_from_imported_user_id(row['uid']) || -1,
            raw: row['body'],
            created_at: Time.zone.at(row['created']),
          }
          h
        else
          puts "No topic found for comment #{row['cid']}"
          nil
        end
      end
    end
  end

  def create_replies
    create_direct_replies
    create_nested_replies
  end

end

if __FILE__==$0
  ImportScripts::DrupalQA.new.perform
end