<?php
class TradeplusModel extends CI_Model
{
    private $apiUrl = 'https://openapi.tradplus.com/v3/deviceReport';

    private $appIds = [ 
        1 => '672DB5BC8604AA1D9C4538CD98F3BA67',
        2 => 'B83254130A198CF611C2421EE3D195FA',
    ];

    private $auth = 'Bearer 56ef310a-d611-4846-89e4-407f35b99389';

    public function downloadFile($url, $locPath){
        if(file_exists($locPath)){
            @unlink($locPath); //删除文件
        }   
        //设置脚本的最大执行时间，设置为0则无时间限制
        set_time_limit(0);
        ini_set('max_execution_time', '0');
        ob_start();
        readfile($url);
        $data  = ob_get_contents();
        ob_end_clean();
        if(!empty($data)){
            file_put_contents($locPath, $data);
            return true;
        }
        return false;
    }

    function downloadFilebak($url, $locPath) {
        if(file_exists($locPath)){
            @unlink($locPath); //删除文件
        }
        //设置脚本的最大执行时间，设置为0则无时间限制
        set_time_limit(0);
        ini_set('max_execution_time', '0');

        //获得文件大小
        $header_array = get_headers($url, true);
        if(isset($header_array[0]) && $header_array[0] == 'HTTP/1.1 404 Not Found'){
            return false;
        }
        $filesize = $header_array['Content-Length'];

        //针对大文件，规定每次读取文件的字节数为4096字节，直接输出数据
        $read_buffer = 4096;

        $handle = fopen($url, 'rb');
        //总的缓冲的字节数
        $sum_buffer = 0;
        //只要没到文件尾，就一直读取
        $h = fopen($locPath, 'wb');
        while(!feof($handle) && $sum_buffer<$filesize) {
            $res = fread($handle,$read_buffer);
            fwrite($h, $res);
            $sum_buffer += $read_buffer;
        }
        //关闭句柄
        fclose($handle);
    }

    private $f = [  //字段对应的偏移量
        'dateTimeStamp'        => 0, //int	时间戳（日期）
        'appId'                => 1, //	String	应用ID （tradplus）
        'placementId'          => 2, //String	广告位ID （tradplus）
        'placementName'        => 3, //String	广告位名字（tradplus）
        'adFormat'             => 4, //	Int	广告位类型
        'adFormatName'         => 5, //String	广告位类型名字
        'area'                 => 6, //	String	国家地区编码(ISO 3166-1二位国家地区代码)
        'network'              => 7, //Int	广告网络ID
        'networkName'          => 8, //String	广告网络名字
        'networkPlacementId'   => 9, //	String	广告网络的广告位ID信息
        'networkPlacementName' => 10, //	String	广告网络的广告源名称 （tradplus）
        'networkPlacementInfo' => 11, //String	广告网络的广告位详细信息
        'androidId'            => 12, //String	设备ID，androidid
        'gaid'                 => 13, //String	Google的广告设备ID
        'idfa'                 => 14, //String	iOS的设备ID
        'userId'               => 15,
        'channel'              => 16,
        'sub_channel'          => 17,
        'impression'           => 18, //Int	展示数（tradplus）
        'click'                => 19, //Int	点击数（tradplus）
        'revenue'              => 20, //Float	收益
        'ecpm'                 => 21, //Float	千次展示收益//
    ];

    public function __construct(){
        parent::__construct();
        $this->load->library('curl');
    }   

    public function loopApiData($date = '') {
        if(empty($date)){
            $date = date('Y-m-d', strtotime("-4 days"));
        }
        ////删除旧数据
        //$tb = 'crazygod_api_statistics.t_tradeplus';
        //$sql = "DELETE FROM {$tb} WHERE day = '".date('Ymd', strtotime($date))."'";
        //oo::commonOprDb('statistics')->query($sql);

        foreach($this->appIds as $sid => $appId){
            $ret = $this->getApiData($date, $appId, $sid);
        }
        return $ret;
    }

    private function getApiData ($date = '', $appId = '', $sid = 1) {
        $params = [
            'date'     => $date,
            'timezone' => 'UTC+0',
            'appId'    => $appId,
        ];
        $params = json_encode($params);
        $header = [
            'Authorization: '.$this->auth,
            'Content-Type: application/json',
        ];
        $tmp = $this->curl->req($this->apiUrl, $params, 20, $header);
        $ret = $tmp ? (array)json_decode($tmp, true) : [];
        if(empty($ret)){
            return false;
        }
        $pathPrefix = BASEPATH."../public/trade_plus_";
        $locPathArr = [];
        foreach($ret as $k => $v){
            //重新拉一次，防止远程文件超时
            $tmp = $this->curl->req($this->apiUrl, $params, 20, $header);
            $ret2 = $tmp ? (array)json_decode($tmp, true) : [];
            if(empty($ret2[$k])){
                continue;
            }
            $locPath = "{$pathPrefix}{$k}_{$sid}.csv";
            $downRet = $this->downloadFile($ret2[$k], $locPath);
            if($downRet){
                $locPathArr[] = $locPath;
            }
        }

        foreach($locPathArr as $url){
            $ret = $this->dealApiData($url);
        }
        return $ret;
    }

    private function dealApiData($csvUrl = '') {
        $content = file_get_contents($csvUrl);
        $arr = explode("\n", $content);
        if($arr){
            @unlink($csvUrl);
        }
        //$data = ['dau' => 0, 'deu' => 0, 'impression' => 0, 'click' => 0];
        $data = [];
        $getGroupUids = $groupUids = $tempUids = [];
        foreach($arr as $k => $v){
            $tmp = explode(',', $v);
            if(empty($tmp[$this->f['userId']]) || empty($tmp[$this->f['userId']])){
                continue;
            }
            $day = date('Ymd', $tmp[$this->f['dateTimeStamp']]);
            $uid = $tmp[$this->f['userId']];
            if(empty($tempUids['uid'])){
                $tempUids[$uid] = [
                    'dau'        => 1,
                    'deu'        => empty($tmp[$this->f['click']]) ? 0 : 1,
                    'impression' => empty($tmp[$this->f['impression']]) ? 0 : $tmp[$this->f['impression']],
                    'ecpm'       => empty($tmp[$this->f['ecpm']]) ? 0 : $tmp[$this->f['ecpm']],
                    'click'      => empty($tmp[$this->f['click']]) ? 0 : $tmp[$this->f['click']],
                    'revenue'    => empty($tmp[$this->f['revenue']]) ? 0 : $tmp[$this->f['revenue']],
                    'day'        => $day,
                ];
            }else{
                $tempUids[$uid]['dau']        += 1;
                $tempUids[$uid]['deu']        += empty($tmp[$this->f['click']]) ? 0 : 1;
                $tempUids[$uid]['impression'] += empty($tmp[$this->f['impression']]) ? 0 : $tmp[$this->f['impression']];
                $tempUids[$uid]['ecpm']       += empty($tmp[$this->f['ecpm']]) ? 0 : $tmp[$this->f['ecpm']];
                $tempUids[$uid]['click']      += empty($tmp[$this->f['click']]) ? 0 : $tmp[$this->f['click']];
                $tempUids[$uid]['revenue']    += empty($tmp[$this->f['revenue']]) ? 0 : $tmp[$this->f['revenue']];
            }
            if(!in_array($uid, $getGroupUids) && !isset($groupUids[$uid])){
                $getGroupUids[] = $uid;
            }
            if(count($tempUids) >= 100){
                if(!empty($getGroupUids)){
                   $groupUids = $this->getUidGroups($getGroupUids, $groupUids);
                }
                $data = $this->turnsToGroupData($tempUids, $groupUids, $data);
                $getGroupUids = $tempUids = [];
            }
        }
        if(!empty($tempUids)){
            if(!empty($getGroupUids)){
                $groupUids = $this->getUidGroups($getGroupUids, $groupUids);
            }
            $data = $this->turnsToGroupData($tempUids, $groupUids, $data);
        }
        //更新到数据库
        if(empty($data)){
            return false;
        }
        return $this->upToDb($data);
    }

    /**
     * 用户分组加载到内存
     * @param array $uids
     * @param array $groupUids
     */
    public function getUidGroups(array $uids, $groupUids) {
        $tb = otable::UserDynamicsData();
        $sql = "SELECT uid, groupId2 FROM {$tb} WHERE uid IN(".implode(",", $uids).")";
        $tmp = oo::commonOprDb('slavedb')->getAll($sql, MYSQLI_ASSOC);
        $userGroupArr = $this->getUserGroupConfig(1);
        foreach($tmp as $v){
            $curGroupId = explode(",",$v['groupId2']);
            if(empty($curGroupId)){
                continue;
            }else foreach ($userGroupArr as $id){
                if(in_array($id,$curGroupId)){
                    $groupUids[$v['uid']] = $id;
                    break;
                }
            }
        }
        return $groupUids;
    }

    /**
     * 获取用户分组配置信息
     */
    public function getUserGroupConfig($cid = 0) {
        $tb = otable::UserGroupConfig(2);
        if($cid){
            $sql = "SELECT * FROM {$tb} WHERE cid={$cid} ORDER BY sort DESC";
        }else{
            $sql = "SELECT * FROM {$tb} ORDER BY sort DESC";
        }
        return oo::commonOprDb('slavedb')->getAll($sql, MYSQLI_ASSOC);
    }

    /**
     * 获取用户分组id对应的分组名配置信息
     */
    public function getUserGroupNamesConfig($cid = 0) {
        $data = $this->getUserGroupConfig($cid);
        return $data ? array_column($data, 'name', 'id') : [];
    }

    /**
     * 转到分组数据里
     * @param array
     * @return array
     */
    public function turnsToGroupData(array $arr = [], $groupUids, $data) {
        foreach($arr as $uid => $v){
            if(!isset($groupUids[$uid])){
                continue;
            }
            $groupId = $groupUids[$uid];
            if(empty($data[$groupId])){
                $data[$groupId] = [
                    'day'        => $v['day'],
                    'groupid'    => $groupId,
                    'dau'        => $v['dau'],
                    'deu'        => $v['deu'],
                    'impression' => $v['impression'],
                    'click'      => $v['click'],
                    'ecpm'       => $v['ecpm'],
                    'revenue'    => $v['revenue'],
                ];
                continue;
            }
            $data[$groupId]['dau']        += $v['dau'];
            $data[$groupId]['deu']        += $v['deu'];
            $data[$groupId]['impression'] += $v['impression'];
            $data[$groupId]['click']      += $v['click'];
            $data[$groupId]['ecpm']       += $v['ecpm'];
            $data[$groupId]['revenue']    += $v['revenue'];
        }
        return $data;
    }

    /**
     * 批量更新到数据库
     * @param array $data
     * @return bool
     */
    public function upToDb(array $data) {
        $tb = 'crazygod_api_statistics.t_tradeplus';
        foreach($data as $v){
            $ret = oo::commonOprDb('statistics')->getOne("SELECT * FROM {$tb} WHERE day = '{$v['day']}' AND groupid = {$v['groupid']}", 1);
            if(empty($ret)){
                $sql = "INSERT INTO {$tb} (day, dau, impression, click, deu, ecpm, groupid, revenue) VALUES";
                $sql .= "('{$v['day']}', '{$v['dau']}', '{$v['impression']}', '{$v['click']}', '{$v['deu']}', '{$v['ecpm']}', '{$v['groupid']}', '{$v['revenue']}')";
                $res = oo::commonOprDb('statistics')->query($sql);
            }else{
                $dau        = $ret['dau'] + $v['dau'];
                $impression = $ret['impression'] + $v['impression'];
                $click      = $ret['click'] + $v['click'];
                $deu        = $ret['deu'] + $v['deu'];
                $ecpm       = $ret['ecpm'] + $v['ecpm'];
                $revenue    = $ret['revenue'] + $v['revenue'];
                $sql = "update {$tb} set dau = {$dau}, impression = {$impression}, click = {$click}, deu = {$deu}, ecpm = {$ecpm}, revenue='{$revenue}' WHERE 'day'= {$v['day']} AND groupid = {$v['groupid']}";
                $res = oo::commonOprDb('statistics')->query($sql);
            }
        }
        return $res;
    }

    /**
     * 获取统计数据
     * @param 
     */
    public function getData($start = '', $end = '', $limit = 10, $offset = 0) {
        if(empty($start)){
            $start = date('Ymd', strtotime('-7 days 0:0:1'));
        }
        if(empty($end)){
            $end = date('Ymd', strtotime('-1 days 23:59:59'));
        }
        $tb = otable::tradeplus();

        $totalSql = "SELECT COUNT(*) AS total FROM {$tb} WHERE  day >= {$start} AND day <= {$end}";
        $total = oo::commonOprDb('statistics')->getOne($totalSql, MYSQLI_ASSOC);
        $data['total'] = $total['total'];

        $sql = "SELECT * FROM {$tb} WHERE day >= {$start} AND day <= {$end}";
        $sql .= " ORDER BY day DESC LIMIT {$limit},{$offset}";
        $arr = oo::commonOprDb('statistics')->getAll($sql,1);
        $data['list'] = $arr;
        return $data;
    }
}
