package mobvista.dmp.datasource.dm

import java.text.SimpleDateFormat
import java.util
import java.util.Date

import com.google.gson.{JsonArray, JsonObject}
import mobvista.dmp.datasource.dm.Constant.{allZero, didPtn, imeiPtn, andriodIdPtn}
import mobvista.dmp.datasource.dm.entity.PackageTag
import mobvista.prd.datasource.util.GsonUtil
import org.apache.commons.lang3.StringUtils
import org.apache.spark.sql.Row

import scala.collection.JavaConversions._
import scala.collection.mutable.ArrayBuffer

/**
  * @package: mobvista.dmp.datasource.dm
  * @author: wangjf
  * @date: 2019/4/16
  * @time: 上午11:48
  * @email: jinfeng.wang@mobvista.com
  * @phone: 152-1062-7698
  */
object InterestTagConstant {
  val app_tag_except_sql: String =
    """
      |SELECT
      |  /*+ MAPJOIN(b) */
      |  a.package_name,
      |  a.platform,
      |  a.tag
      |FROM (
      |       SELECT
      |         t.package_name,
      |         CASE WHEN t.platform = 'ios' THEN 'ios' ELSE 'android' END AS platform,
      |         t.tag
      |       FROM dwh.dim_app_tag t
      |       WHERE concat(t.year, t.month, t.day) = '@date'
      |     ) a
      |LEFT OUTER JOIN dwh.dim_package_tags b
      |    ON a.package_name = b.package_name AND a.platform = b.platform
      |WHERE b.package_name IS NULL
    """.stripMargin

  val tag_sql_v2: String =
    """
      |SELECT /*+ MAPJOIN(t) */ s.package_name, CAST(COLLECT_SET(str2Json(t.tag_id, t.first_tag, t.second_tag)) AS string) tags, COLLECT_SET(t.tag_id) tag_ids
      | FROM dwh.dm_old2new_tag t
      | JOIN
      | (SELECT package_name, platform, tag_type, first_tag, second_tag
      |   FROM t_app_two_tags
      |   UNION
      |   SELECT package_name, platform, tag_type, first_tag, second_tag FROM
      |   dwh.dim_package_tags
      | ) s
      | ON UPPER(CONCAT(t.tag_type, '-', t.first_tag, '-', t.second_tag)) = UPPER(CONCAT(s.tag_type, '-', s.first_tag, '-', s.second_tag))
      | GROUP BY s.package_name
    """.stripMargin

  val tag_sql: String =
    """
      |SELECT /*+ MAPJOIN(a) */ b.package_name, b.platform, CAST(COLLECT_SET(str2Json(a.tag_id, b.first_tag, b.second_tag)) AS string) tags
      | FROM dwh.dm_old2new_tag a
      | JOIN
      | (SELECT /*+ MAPJOIN(a) */ b.package_name as package_name, b.platform as platform, b.tag_type as tag_type, a.new_first_tag_1 as first_tag, a.new_second_tag_1 as second_tag
      |   from dwh.dim_category_mv_new a
      |   JOIN t_app_two_tags b ON a.mv_first_tag = b.first_tag AND a.mv_second_tag = b.second_tag
      |   GROUP BY b.package_name, b.platform, b.tag_type, a.new_first_tag_1, a.new_second_tag_1
      |   UNION
      |   SELECT package_name, platform, tag_type, first_tag, second_tag FROM
      |   dwh.dim_package_tags
      | ) b
      | ON UPPER(CONCAT(a.tag_type, '-', a.first_tag, '-', a.second_tag)) = UPPER(CONCAT(b.tag_type, '-', b.first_tag, '-', b.second_tag))
      | GROUP BY b.package_name, b.platform
    """.stripMargin

  def flatInterest(row: Row): Array[PackageTag] = {
    val buffer = new ArrayBuffer[PackageTag]()
    GsonUtil.String2JsonArray(row.getString(2))
      .foreach(element => {
        val obj = element.getAsJsonObject
        val firstTag = obj.get("1").getAsString
        val secondTag = if (obj.get("2") != null) obj.get("2").getAsString else ""
        buffer += PackageTag(row.getString(0), row.getString(1), "category", firstTag, secondTag)
      })
    buffer.toArray
  }

  def str2Json(tag_id: String, first_tag: String, second_tag: String): String = {
    val jsonObject = new JsonObject
    jsonObject.addProperty("id", tag_id)
    jsonObject.addProperty("1", first_tag)
    if (StringUtils.isNotBlank(second_tag)) {
      jsonObject.addProperty("2", second_tag)
    }
    jsonObject.toString
  }

  val interest_sql_case: String =
    """
      |SELECT device_id, MAX(device_type) device_type, MAX(platform) platform, @combineJson(concat_ws(';',collect_set(tags))) tags FROM
      | (SELECT LOWER(device_id) device_id, device_type, platform, tags
      |   FROM dev.dm_interest_tag WHERE CONCAT(year, month, day) = '@date'
      |   AND business = '3s' AND @check_deviceId
      | ) interest_tag GROUP BY device_id
    """.stripMargin

  val interest_sql: String =
    """
      |SELECT device_id, MAX(device_type) device_type, MAX(platform) platform, @combineJson(concat_ws(';',collect_set(tags))) tags FROM
      | (SELECT LOWER(device_id) device_id, device_type, platform, tags
      |   FROM dwh.dm_interest_tag WHERE CONCAT(year, month, day) = '@date'
      |   AND business IN ('adn_install','adn_request_sdk','adn_request_other','dsp_req','other','3s','mp','clever','adn_sdk') AND @check_deviceId
      |   UNION ALL
      |   SELECT LOWER(device_id) device_id, device_type, platform, tags
      |   FROM dwh.dm_interest_tag WHERE CONCAT(year, month, day) = '@ga_date' AND business IN ('ga_device','ga') AND @check_deviceId
      | ) interest_tag GROUP BY device_id
    """.stripMargin

  def check_deviceId(device_id: String): Boolean = {
    device_id.matches(didPtn) && !device_id.equals(allZero) || device_id.matches(imeiPtn) || device_id.matches(andriodIdPtn)
  }

  def combineJsonArray(tags: String): String = {
    val jsonArray = new JsonArray
    val map: java.util.Map[String, (Date, JsonObject)] = new util.HashMap[String, (Date, JsonObject)]()
    val sdf: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
    tags.split(";").foreach(tag => {
      val jsonNode = GsonUtil.String2JsonArray(tag)
      for (i <- 0 until jsonNode.size) {
        val json = jsonNode.get(i).getAsJsonObject
        if (!json.has("package_name") || !json.has("date")) {
          jsonArray.add(json)
        } else if (map.keySet.contains(json.get("package_name").getAsString)) {
          if (map.get(json.get("package_name").getAsString)._1.before(sdf.parse(json.get("date").getAsString))) {
            map.put(json.get("package_name").getAsString, (sdf.parse(json.get("date").getAsString), json))
          }
        } else {
          map.put(json.get("package_name").getAsString, (sdf.parse(json.get("date").getAsString), json))
        }
      }
    })
    import scala.collection.JavaConversions._
    for (key <- map.keySet()) {
      jsonArray.add(map.get(key)._2)
    }
    jsonArray.toString
  }
}