import os
import sys

sys.path.append(os.path.dirname(sys.path[0]))
from pyspark.sql.types import StringType, MapType
from utils.common_util import CommonUtil, DateTypes
from utils.hdfs_utils import HdfsUtils
from utils.spark_util import SparkUtil
from utils.db_util import DBUtil
from pyspark.sql import functions as F
import numpy as np

class DwtStMtChristmasInfo(object):
    def __init__(self, site_name, date_type, date_info):
        self.site_name = site_name
        self.date_type = date_type
        self.date_info = date_info
        self.hive_tb = "dwt_st_mt_christmas_info"
        self.partition_dict = {
            "site_name": site_name,
            "date_type": date_type,
            "date_info": date_info
        }
        # 落表路径校验
        self.hdfs_path = CommonUtil.build_hdfs_path(self.hive_tb, partition_dict=self.partition_dict)

        # 注册自定义函数 (UDF)
        self.u_theme_pattern = F.udf(self.udf_theme_pattern, StringType())

        # 创建spark_session对象相关
        app_name = f"{self.__class__.__name__}:{site_name}:{date_info}"
        self.spark = SparkUtil.get_spark_session(app_name)

        # 全局df初始化
        self.df_st = self.spark.sql(f"select 1+1;")
        self.df_st_info = self.spark.sql(f"select 1+1;")
        self.df_st_asin_info = self.spark.sql(f"select 1+1;")
        self.df_asin_order_info = self.spark.sql(f"select 1+1;")
        self.df_asin_launchtime_info = self.spark.sql(f"select 1+1;")
        self.df_self_asin = self.spark.sql(f"select 1+1;")
        self.df_st_handle = self.spark.sql(f"select 1+1;")
        self.df_mt_volume = self.spark.sql(f"select 1+1;")

        # 其他变量
        self.theme_list_str = str()  # 正则匹配

    @staticmethod
    def udf_theme_pattern(parttern_text, theme_list_str):
        found_themes = [theme.strip() for theme in eval(theme_list_str) if theme in parttern_text]
        if found_themes:
            return ','.join(set(found_themes))
        else:
            return None

    def read_data(self):
        print("======================查询sql如下======================")
        # 获取搜索词及搜索词下搜索产品总数
        sql = f"""
                select search_term, 
                       cast(quantity_being_sold as int) as st_quantity_being_sold from (
                select search_term,
                       quantity_being_sold,
                       row_number() over (partition by search_term order by created_time desc) as rank_flag
                from ods_st_quantity_being_sold
                where site_name = '{self.site_name}'
                and date_type = 'month'
                and date_info = '{self.date_info}'
                and search_term like '%christmas%') t1
                where t1.rank_flag=1
            """
        self.df_st_info = self.spark.sql(sql)

        # 获取搜索词与asin的关系
        sql = f"""
            select
                search_term,
                asin
            from dwd_st_asin_measure
            where site_name = '{self.site_name}'
              and date_type = '{self.date_type}'
              and date_info = '{self.date_info}'
              and search_term like '%christmas%'
        """
        print(sql)
        self.df_st_asin_info = self.spark.sql(sql)

        # 获取asin的销量相关数据
        sql = f"""
                select
                       asin,
                       asin_bsr_orders,
                       asin_zr_orders_sum
                from dwd_asin_measure
                where site_name = '{self.site_name}'
                  and date_type = '{self.date_type}'
                  and date_info = '{self.date_info}'
                        """
        print(sql)
        self.df_asin_order_info = self.spark.sql(sql)

        # 获取asin详情中的上架日期数据
        sql = f"""
                        select
                               asin,
                               asin_launch_time,
                               case when(datediff(`current_date`(),to_date(asin_launch_time)) <= 90) then 1 end as is_new_flag
                        from dim_asin_detail
                        where site_name = '{self.site_name}'
                          and date_type = '{self.date_type}'
                          and date_info = '{self.date_info}'
               """
        print(sql)
        self.df_asin_launchtime_info = self.spark.sql(sql)

        # 读取ods_self_asin,获得公司内部asin信息
        sql = f"""select 
                    asin,
                    1 as is_self_asin 
              from ods_self_asin 
              where site_name='{self.site_name}' group by asin """
        print(sql)
        self.df_self_asin = self.spark.sql(sqlQuery=sql)

        # 读取Merchantwords中的对应christmas的搜索量
        sql = f"""
                select
                keyword as search_term,
                volume as mt_volume
                from dwt_merchantwords_st_detail
                where site_name='{self.site_name}'
                and keyword like '%christmas%'   
        """
        print(sql)
        self.df_mt_volume = self.spark.sql(sqlQuery=sql)

    def handle_data(self):
        self.read_data()
        self.handle_st_data()
        self.save_data()

    def handle_st_data(self):
        # 关联处理好搜索词和asin的关系
        self.df_st_asin_info = self.df_st_asin_info.join(
            self.df_st_info, on=['search_term'], how='inner'
        ).cache()

        # 关联必要的数据
        self.df_st_handle = self.df_st_asin_info.join(
            self.df_asin_order_info, on=['asin'], how='left'
        ).join(
            self.df_asin_launchtime_info, on=['asin'], how='left'
        ).join(
            self.df_self_asin, on=['asin'], how='left'
        )

        # 计算各类搜索词占比数据
        self.df_st_handle = self.df_st_handle.groupby(['search_term']).agg(
            F.max('st_quantity_being_sold').alias('total_searched_products'),
            F.count('asin').alias('total_page3_products'),
            F.sum('is_self_asin').alias('total_self_products'),
            F.sum('asin_bsr_orders').alias('total_bsr_orders'),
            F.sum('asin_zr_orders_sum').alias('total_orders'),
            F.sum('is_new_flag').alias('total_new_products')
        )
        self.df_st_handle = self.df_st_handle.join(
            self.df_mt_volume, on=['search_term'], how='left'
        )


    def save_data(self):
        df_save = self.df_st_handle.select(
            F.col('search_term'),
            F.col('mt_volume'),
            F.col('total_searched_products'),
            F.col('total_page3_products'),
            F.col('total_self_products'),
            F.round(F.col('total_self_products')/F.col('total_page3_products'), 4).alias('self_product_rate'),
            F.col('total_bsr_orders'),
            F.col('total_orders'),
            F.col('total_new_products'),
            F.round(F.col('total_new_products') / F.col('total_page3_products'), 4).alias('new_product_rate'),
            F.date_format(F.current_timestamp(), 'yyyy-MM-dd HH:mm:SS').alias('created_time'),
            F.date_format(F.current_timestamp(), 'yyyy-MM-dd HH:mm:SS').alias('updated_time'),
            F.lit(self.site_name).alias('site_name'),
            F.lit(self.date_type).alias('date_type'),
            F.lit(self.date_info).alias('date_info')
        )
        # CommonUtil.check_schema(self.spark, df_save, self.hive_tb)

        print(f"清除hdfs目录中:{self.hdfs_path}")
        HdfsUtils.delete_file_in_folder(self.hdfs_path)

        df_save = df_save.repartition(10)
        partition_by = ["site_name", "date_type", "date_info"]
        print(f"当前存储的表名为：{self.hive_tb},分区为{partition_by}", )
        df_save.write.saveAsTable(name=self.hive_tb, format='hive', mode='append', partitionBy=partition_by)
        print("success")







if __name__ == '__main__':
    site_name = CommonUtil.get_sys_arg(1, None)
    date_type = CommonUtil.get_sys_arg(2, None)
    date_info = CommonUtil.get_sys_arg(3, None)  # 参数3：年-周/年-月/年-季/年-月-日, 比如: 2022-1
    assert site_name is not None, "site_name 不能为空！"
    assert date_type is not None, "date_type 不能为空！"
    assert date_info is not None, "date_info 不能为空！"
    obj = DwtStMtChristmasInfo(site_name=site_name, date_type=date_type, date_info=date_info)
    obj.handle_data()