<?php
/**
 * Created by PhpStorm.
 * User: z_yang
 * Date: 2018/03/09
 * Time: 20:18
 */

namespace App\Modules\Statistic\Services;

use App\Modules\Statistic\Models\WapVisitStat;
use App\Modules\SendOrder\Models\SendOrder;
use App\Modules\Subscribe\Services\OrderService;
use DB;
use Redis;

class WapVisitStatService
{

    /**
     * 获取派单总pv
     * @param int $id
     */
    public static function getSendOrderTotalPv($id)
    {
        //return (int)Redis::hget('send_order_pv_' . $id, 'total');
        $today = (int)Redis::hget('send_order_pv_'.$id,date('Y-m-d'));
        $old = (int)WapVisitStat::where('key', $id)->where('type', 3)->where('from_type','send_orders')->sum('pv');
        return $today+$old;
    }

    /**
     * 获取浏览器派单总pv uv
     * @param $id
     * @return array
     */
    public static function getBrowserSendOrderTotalPvAndUv($id):array
    {
        $sql_format = "select sum(pv) as pv,sum(uv) as uv from wap_visit_stats WHERE `key`=%s and from_type='%s'  and `type`=3 ";
        $sql = sprintf($sql_format, $id, 'browser_send_orders');
        $today_pv = (int)Redis::hget('browser_send_order_pv_' . $id, date('Y-m-d'));
        $today_uv = (int)Redis::hget('browser_send_order_uv_' . $id, date('Y-m-d'));
        $res = DB::select($sql);
        $uv = (int)$res[0]->uv + $today_uv;
        $pv = (int)$res[0]->pv + $today_pv;
        return compact('uv', 'pv');
    }


    /**
     * 获取派单总pv
     * @param $id int
     */
    public static function getSendOrderTotalUv($id)
    {
        //return (int)Redis::hget('send_order_uv_' . $id, 'total');
        $today = (int)Redis::hget('send_order_uv_'.$id,date('Y-m-d'));
        $old = WapVisitStat::where('key', $id)->where('type', 3)->where('from_type','send_orders')->sum('uv');
        return $today+$old;
    }


    /**
     * 获取活动的pv uv
     * @param int $channel_id
     * @param int $activity_id
     * @return array
     */
    public static function getActivityUvAndPv(int $channel_id, int $activity_id):array
    {
        $day = date('Y-m-d');
        $uv_key_format = 'activity:%s:distribution_channel_id:%s:date:%s:uv';
        $pv_key_format = 'activity:%s:distribution_channel_id:%s:pv';
        $sql_format = "select sum(pv) as pv,sum(uv) as uv from wap_visit_stats WHERE `key`=%s and from_type='%s' and `day` >= '2018-01-10' and type=2 ";
        $sql = sprintf($sql_format, $channel_id, $activity_id);
        $res = DB::select($sql);
        $today_pv = (int)Redis::hget(sprintf($pv_key_format, $activity_id, $channel_id), $day);
        $today_uv = (int)Redis::scard(sprintf($uv_key_format, $activity_id, $channel_id, $day));
        $uv = $res[0]->uv + $today_uv;
        $pv = $res[0]->pv + $today_pv;
        return compact('uv', 'pv');
    }

    /**
     * 获取活动的pv uv
     * @param int $channel_id
     * @param int $activity_id
     * @param string $day
     * @return array
     */
    public static function getActivityUvAndPvByDay(int $channel_id, int $activity_id, string $day):array
    {
        $sql_format = "select sum(pv) as pv,sum(uv) as uv from wap_visit_stats WHERE `key`=%s and from_type='%s' and `day` = '%s' and type=2 ";
        $sql = sprintf($sql_format, $channel_id, $activity_id, $day);
        $res = DB::select($sql);
        $uv = $res[0]->uv;
        $pv = $res[0]->pv;
        return compact('uv', 'pv');
    }

    /**
     * 获取派单每一天的Uv信息列表
     * @param $id int
     * @return array  UV
     */
    public static function getSendOrderUv($id)
    {
        $now = date('Y-m-d');
        $res = WapVisitStat::where('key', $id)->where('type', 3)->where('from_type', 'send_orders')->select('day', 'uv')->get();
        $data = [];
        $total = 0;
        if ($res) {
            foreach ($res as $v) {
                $data[$v->day] = $v->uv;
                $total += $v->uv;
            }
            $data['total'] = $total;
        }
        $today = (int)Redis::hget('send_order_uv_' . $id, $now);
        $data[$now] = $today;
        return $data;
    }

    /**
     * 获取派单某一天的UvPV
     * @param $id int
     * @return array  UvPV
     */
    public static function getSendOrderDayUvPvFromStat($id,$date)
    {
        $res = WapVisitStat::where('key', $id)->where('type', 3)->where('from_type', 'send_orders')->where('day',$date)->select('uv','pv')->first();
        $uv = $res ? $res->uv : 0;
        $pv = $res ? $res->pv : 0;
        return compact('uv','pv');
    }

    /**
     * 获取每一天的pv信息列表
     * @param $id int
     * @return array $data
     */
    public static function getSendOrderPv($id)
    {
        $now = date('Y-m-d');
        $res = WapVisitStat::where('key', $id)->where('type', 3)->where('from_type', 'send_orders')->select('day', 'pv')->get();
        $data = [];
        $total = 0;
        if ($res) {
            foreach ($res as $v) {
                $data[$v->day] = $v->pv;
                $total += $v->pv;
            }
            $data['total'] = $total;
        }
        $today = (int)Redis::hget('send_order_pv_' . $id, $now);
        $data[$now] = $today;
        return $data;
    }

    //获取推广总uv、pv
    public static function getChannelPromotionTotalUvPv($distribution_channel_id, $date)
    {
        $sql_format = "select sum(wap_visit_stats.uv) as uv,sum(wap_visit_stats.pv) as pv from send_orders  join wap_visit_stats on send_orders.id=wap_visit_stats.key and wap_visit_stats.type=3 and wap_visit_stats.from_type='send_orders' and wap_visit_stats.day='%s' where distribution_channel_id=%d";
        $sql = sprintf($sql_format, $date, $distribution_channel_id);
        $res = DB::select($sql);
        $uv = $res[0]->uv;
        $pv = $res[0]->pv;
        return compact('uv', 'pv');
    }

    /**
     *获取site下的uv,pv
     */
    public static function getSitePvAndUv($distribution_channel_id, $from, $start_day, $end_day)
    {
        $res = WapVisitStat::where('key', $distribution_channel_id)
            ->where('type', 1)
            ->where('from_type', $from);
        if ($start_day) {
            $res = $res->where('day', '>=', $start_day);
        }
        if ($end_day) {
            $res = $res->where('day', '<=', $end_day);
        }
        $res = $res->select(DB::raw('sum(uv) as uv'), DB::raw('sum(pv) as pv'))
            ->get();
        $temp = $res->first();
        $pv = $temp->pv;
        $uv = $temp->uv;
        $now = date('Y-m-d');
        if ($end_day && $end_day == $now) {
            $pv += (int)Redis::hget('customer:push:click:distribution_channel_id:' . $distribution_channel_id . 'from:' . $from, $now);
            $uv += (int)Redis::scard('push:distribution_channel_id:' . $distribution_channel_id . 'from:' . $from . ':date:' . $now);
        }
        if (!$end_day) {
            $pv += (int)Redis::hget('customer:push:click:distribution_channel_id:' . $distribution_channel_id . 'from:' . $from, $now);
            $uv += (int)Redis::scard('push:distribution_channel_id:' . $distribution_channel_id . 'from:' . $from . ':date:' . $now);
        }
        return compact('uv', 'pv');
    }

    /**
     * 获取某天的uvAndpv
     * @param int $distribution_channel_id
     * @param string $from
     * @param string $day
     * @return array
     */
    public static function getSitePvAndUvOneDay(int $distribution_channel_id, string $from, string $day):array
    {
        $res = WapVisitStat::where('key', $distribution_channel_id)
            ->where('type', 1)
            ->where('from_type', $from)
            ->where('day', '=', $day)
            ->select('pv', 'uv')
            ->first();
        if ($res)
            return ['pv' => $res->pv, 'uv' => $res->uv];
        else {
            return ['pv' => 0, 'uv' => 0];
        }
    }

    /**
     * 获取强关前一张的uv,pv
     */
    public static function getBeforeForceSubAndBeforeVipUv($bid, $send_order_id, $date, $one_day)
    {
        if ($one_day) {
            $res = WapVisitStat::where('key', $bid)->where('from_type', (string)$send_order_id)->where('type', 4)->where('day', $date)->select('uv', 'pv')->first();
        } else {
            $res = WapVisitStat::where('key', $bid)
                ->where('from_type', (string)$send_order_id)
                ->where('type', 4)
                ->where('day', '>=', $date)
                ->where('day', '<=', date('Y-m-d'))
                ->select(DB::raw('sum(uv) as uv'), DB::raw('sum(pv) as pv'))
                ->get();
            $res = $res->first();
        }
        $beforevippv = 0;
        $beforevipuv = 0;
        if ($res) {
            $beforevippv = $res->pv;
            $beforevipuv = $res->uv;
        }

        $res = null;
        if ($one_day) {
            $res = WapVisitStat::where('key', $bid)->where('from_type', (string)$send_order_id)->where('type', 5)->where('day', $date)->select('uv', 'pv')->first();
        } else {
            $res = WapVisitStat::where('key', $bid)
                ->where('from_type', (string)$send_order_id)
                ->where('type', 5)
                ->where('day', '>=', $date)
                ->where('day', '<=', date('Y-m-d'))
                ->select(DB::raw('sum(uv) as uv'), DB::raw('sum(pv) as pv'))
                ->get();
            $res = $res->first();
        }
        $beforeforcesubpv = 0;
        $beforeforcesubuv = 0;
        if ($res) {
            $beforeforcesubpv = $res->pv;
            $beforeforcesubuv = $res->uv;
        }
        return compact('beforevipuv', 'beforevippv', 'beforeforcesubpv', 'beforeforcesubuv');
    }

    public static function getUvAndPVByFromAndDay($distribution_channel_id, $from, $day)
    {
        $from = array_map(function ($i) {
            return sprintf("'%s'", $i);
        }, $from);
        $from_str = implode(',', $from);
        if ($day) {
            if (is_string($day)) {
                $sql_fromat = "select sum(uv) as uv,sum(pv) as pv from wap_visit_stats where `type`=1 and `key`=%s and from_type in (%s) and `day`='%s'";
                $sql = sprintf($sql_fromat, $distribution_channel_id, $from_str, $day);
            } else {
                $sql_fromat = "select sum(uv) as uv,sum(pv) as pv from wap_visit_stats where `type`=1 and `key`=%s and from_type in (%s) and `day` BETWEEN '%s' and '%s'";
                $sql = sprintf($sql_fromat, $distribution_channel_id, $from_str, $day[0], $day[1]);
            }
        } else {
            $sql_fromat = "select sum(uv) as uv,sum(pv) as pv from wap_visit_stats where `type`=1 and `key`=%s and from_type in (%s)";
            $sql = sprintf($sql_fromat, $distribution_channel_id, $from_str);
        }

        $res = DB::select($sql);
        $uv = $res[0]->uv;
        $pv = $res[0]->pv;
        return compact('uv', 'pv');
    }

    public static function smartPushTestBookStats(int $bid)
    {
        $data = [
            'uv' => 0,
            'pv' => 0,
            'charge_amount' => 0,
            'charge_user_num' => 0,
            'book_amount' => 0,
            'book_user_num' => 0,
            'real_push_user_num' => 0,
            'second_chapter_uv' => 0
        ];
        if (empty($bid))
            return $data;
        $uv_key = sprintf('%s_%s_uv', $bid, 'smart_push');
        $uv = (int)(Redis::scard($uv_key));
        $pv = (int)Redis::hget('smart_push_test_book', $bid);
        $book_user_num = Redis::scard('smart_push_test_book_user_count' . $bid);
        $field = sprintf('%s_amount', $bid);
        $book_amount = Redis::hget('smart_push_test_book', $field);
        $real_push_user_num = (int)Redis::hget('SmartPushBookUserNum', $bid);
        $data['uv'] = $uv;
        $data['pv'] = $pv;
        $data['book_amount'] = $book_amount;
        $data['book_user_num'] = $book_user_num;
        $data['real_push_user_num'] = $real_push_user_num;
        $data['second_chapter_uv'] = (int)Redis::scard('smart_push_test_book_second_uv' . $bid);
        return $data;
    }

    public static function customerAllStats($from)
    {
        $uv = Redis::scard('push:distribution_channel_id:alluv:from:' . $from);
        $pv = Redis::hget('push:distribution_channel_id:allpv', $from);
        $pay_user_num = Redis::scard('push:all:paidnum:from:' . $from);
        $charge_amount = Redis::hget('push:all:paidamount', $from);
        $register_user_num = 0;
        return compact('uv', 'pv', 'pay_user_num', 'charge_amount', 'register_user_num');
    }

    /**
     * 内部派单统计
     * @param $from
     * @return array
     */
    public static function innerCustomerAllStats($from)
    {
        $uv = Redis::scard('push:inner_send_order_id:uv:' . $from);
        $pv = Redis::hget('push:inner_send_order_id:pv', $from);
        $order_info = OrderService::getInnerSendOrderStats($from);
        $pay_user_num = 0;
        $charge_amount = 0;
        if ($order_info) {
            $pay_user_num = $order_info->pay_user_num;
            $charge_amount = $order_info->charge_amount;
        }
        $register_user_num = 0;
        return compact('uv', 'pv', 'pay_user_num', 'charge_amount', 'register_user_num');
    }

    /**
     * 211站点特殊统计
     * @param int $uid
     * @param int $bid
     * @param int $send_order_id
     */
    public static function specialChannelIdStatsMarkUser(int $uid,int $bid,int $send_order_id):void
    {
        if(!$uid || !$bid || !$send_order_id){
            return ;
        }
        try{
            if(!Redis::Sismember('specialChannelIdStatsMarkUser:set:'.$uid,$bid)){
                Redis::sadd('specialChannelIdStatsMarkUser:set:'.$uid,$bid);
                $key = $uid.'-'.$bid;
                Redis::hset('specialChannelIdStatsMarkUser:hash:',$key,$send_order_id);
            }
        }catch (\Exception $e){}
        return ;
    }

    /**
     * 211站点特殊统计
     * @param int $uid
     * @param int $bid
     * @return int
     */
    public static function specialChannelIdStatsGetSendOrder(int $uid,int $bid):int{
        if(!$uid || !$bid ){
            return 0;
        }
        try{
            $key = $uid.'-'.$bid;
            $send_order_id = Redis::hget('specialChannelIdStatsMarkUser:hash:',$key);
            if($send_order_id) {
                return (int)$send_order_id;
            }
        }catch (\Exception $e){}
        return 0;
    }

    /**
     * 211站点特殊统计
     * @param int $uid
     * @param $bid
     * @param int $fee
     */
    public static function specialChannelIdStatsSave(int $uid,$bid,int $fee):void{
        if(!$uid || !$bid || !$fee){
            return ;
        }
        $send_order_id = self::specialChannelIdStatsGetSendOrder($uid,$bid);
        if(!$send_order_id){
            return ;
        }
        try{
            $day = date('Y-m-d');
            Redis::HINCRBY('specialChannelIdStats:hash',$send_order_id.'_'.$day,$fee);
            Redis::HINCRBY('specialChannelIdStats:hash',$send_order_id,$fee);
            $set_key = 'specialChannelIdStats:set:sendorder:%s:day:%s';
            Redis::sadd(sprintf($set_key,$send_order_id,$day),$uid);
            Redis::sadd(sprintf($set_key,$send_order_id,'all'),$uid);
        }catch (\Exception $e){}
        return ;
    }

    /**
     * 获取 211站点特殊统计
     * @param int $send_order_id
     * @param string $start_date
     * @return array
     */
    public static function getSpecialChannelIdStats(int $send_order_id,string $start_date):array{
        $data = [
            'first_day_subscribe_num'=>0,//首日累计订阅人数
            'first_day_subscribe_amount'=>0,//首日累计订阅总额
            'three_day_subscribe_num'=>0,// 三日累计订阅人数
            'three_day_subscribe_amount'=>0,//三日累计订阅总额
            'total_subscribe_num'=>0,//累计订阅人数
            'total_subscribe_amount'=>0//累计订阅总额
        ];
        if(!$send_order_id || !$start_date){
            return $data;
        }
        try{
            $set_key = 'specialChannelIdStats:set:sendorder:%s:day:%s';
            $data['first_day_subscribe_num'] = (int)(Redis::scard(sprintf($set_key,$send_order_id,$start_date)));
            $data['first_day_subscribe_amount'] = (int)(Redis::hget('specialChannelIdStats:hash',$send_order_id.'_'.$start_date));
            $data['total_subscribe_num'] = (int)(Redis::scard(sprintf($set_key,$send_order_id,'all')));
            $data['total_subscribe_amount'] = (int)(Redis::hget('specialChannelIdStats:hash',$send_order_id));

            $second_day = date('Y-m-d',strtotime($start_date)+86400);
            $three_day = date('Y-m-d',strtotime($second_day)+86400);
            //$second_day_subscribe_num = (int)(Redis::scrad(sprintf($set_key,$send_order_id,$second_day)));
            $second__day_subscribe_amount = (int)(Redis::hget('specialChannelIdStats:hash',$send_order_id.'_'.$second_day));

            //$three_day_subscribe_num = (int)(Redis::scrad(sprintf($set_key,$send_order_id,$three_day)));
            $three__day_subscribe_amount = (int)(Redis::hget('specialChannelIdStats:hash',$send_order_id.'_'.$three_day));

            Redis::SUNIONSTORE(
                'SpecialChannelIdStatstemp',
                sprintf($set_key,$send_order_id,$start_date),
                sprintf($set_key,$send_order_id,$second_day),
                sprintf($set_key,$send_order_id,$three_day)
            );
            $data['three_day_subscribe_num'] = (int)( Redis::scard('SpecialChannelIdStatstemp') );
            Redis::del('SpecialChannelIdStatstemp');
            $data['three_day_subscribe_amount'] = $second__day_subscribe_amount+$three__day_subscribe_amount+$data['first_day_subscribe_amount'];
        }catch (\Exception $e){}
        return $data;
    }

    /**
     * 阅读器uv pv 统计
     * @param $uid
     * @param $distribution_channel_id
     */
    public static function recordReaderUvAndPv($uid,$distribution_channel_id){
        if(empty($uid) || empty($distribution_channel_id)){
            return ;
        }
        $day = date('Y-m-d');
        $uv_key = sprintf('readeruv:date:%s:channel_id:%s',$day,$distribution_channel_id);
        $pv_key = sprintf('readerpv:channel_id:%s',$distribution_channel_id);
        $record_key = sprintf('recordReaderUvAndPv:date:%s',$day);
        try{
            Redis::sadd($uv_key,$uid);
            Redis::HINCRBY($pv_key,$day,1);
            Redis::sadd($record_key,$distribution_channel_id);
        }catch (\Exception $e){

        }
    }

    /**
     * 获取阅读器uv pv 统计 ['day'=>'2018-12-25','pv'=>1,'uv'=>3];
     *  [ ['day'=>'2018-12-25','pv'=>1,'uv'=>3], ['day'=>'2018-12-26','pv'=>2342,'uv'=>342]];
     * @param $distribution_channel_id
     * @param string $day
     * @return array
     */
    public static function getReaderUvAndPv($distribution_channel_id,$day=''){
        $pv_key = sprintf('readerpv:channel_id:%s',$distribution_channel_id);
        if($day){
            $pv  = (int)Redis::hget($pv_key,$day);
            $uv_key = sprintf('readeruv:date:%s:channel_id:%s',$day,$distribution_channel_id);
            $uv = Redis::scard($uv_key);
            return ['day'=>$day,'pv'=>$pv,'uv'=>$uv];
        }

        $all_pv = Redis::hgetAll($pv_key);
        if(!$all_pv){
            return [];
        }
        $data = [];
        foreach ($all_pv as $d=>$v){
            $uv_key = sprintf('readeruv:date:%s:channel_id:%s',$d,$distribution_channel_id);
            $uv = Redis::scard($uv_key);
            $data[] = ['day'=>$d,'pv'=>$v,'uv'=>$uv];
        }
        return $data;
    }

    /**
     * 保存到数据库后，删除数据
     * @param $date
     */
    public static function deleteReaderUvAndPvRedisKey($date){
        $id_key = sprintf('recordReaderUvAndPv:date:%s',$date);
        $channel_ids = Redis::smembers($id_key );
        if($channel_ids){
            foreach ($channel_ids as $channel_id){
                $pv_key = sprintf('readerpv:channel_id:%s',$channel_id);
                Redis::hdel($pv_key,$date);
                $uv_key = sprintf('readeruv:date:%s:channel_id:%s',$date,$channel_id);
                Redis::del($uv_key);
            }
        }
        Redis::del($id_key);
    }
}