<?php namespace Phpcmf\Model\Weixin;

class Weixin extends \Phpcmf\Model
{

    // 发送通知
    public function send_notice($value, $siteid, $error) {

        $content = [];
        if (isset($value['config']['weixin']['tpl_content']) && is_array($value['config']['weixin']['tpl_content'])) {
            $content = $value['config']['weixin']['tpl_content'];
            if (!$content) {
                $error[] = $debug = '自定义通知内容参数tpl_content不存在';
                CI_DEBUG && log_message('debug', '通知任务（'.$value['name'].'）微信执行失败：'.$debug);
            }
        } else {
            $rt = \Phpcmf\Service::L('notice')->_get_tpl_content($siteid, $value['name'], 'weixin', $value['data']);
            if (!$rt['code']) {
                $error[] = $rt['msg'];
                CI_DEBUG && log_message('debug', '通知任务（'.$value['name'].'）执行失败：'.$rt['msg']);
            } else {
                $xml = \Phpcmf\Service::L('notice')->_xml_array($rt['msg']);
                if (!$xml || !isset($xml['xml']) || !$xml['xml']) {
                    $error[] = $debug = 'xml解析失败，检查文件格式是否正确：'.$value['name'].'.html';
                    CI_DEBUG && log_message('debug', '通知任务（'.$value['name'].'）微信执行失败：'.$debug.'<br>'.$rt['msg']);
                } else {
                    $content = $xml['xml'];
                }
            }
        }
        if ($content) {
            $rt = \Phpcmf\Service::M('member')->weixin_template($value['data']['uid'], $content['id'], $content['param'], $content['url']);
            if (!$rt['code']) {
                $error[] = $debug = '微信消息执行错误：'.$rt['msg'];
                CI_DEBUG && log_message('debug', '通知任务（'.$value['name'].'）微信执行失败：'.$debug);
            } else {
                // 成功
                unset($value['config']['weixin']);
            }
        }
        return [$error, $value];
    }

    // 获取微信表名
    public function wxtable($name) {
        return weixin_wxtable($name);
    }

    // 获取配置信息
    public function get_config($name) {

        $data = $this->db->table(weixin_wxtable('weixin'))->where('name', $name)->get()->getRowArray();
        if ($data) {
            $data = dr_string2array($data['value']);
            return $data;
        } else {
            $this->db->table(weixin_wxtable('weixin'))->insert([
                'name' => $name,
                'value' => '',
            ]);
            return [];
        }
    }

    // 存储配置信息
    public function save_config($name, $post) {

        $rt = $this->db->table(weixin_wxtable('weixin'))->replace([
            'name' => $name,
            'value' => dr_array2string($post),
        ]);

        if ($rt->connID->error) {
            return dr_return_data(0, $this->table.': '.$rt->connID->error);
        }

        return dr_return_data(1);
    }

    // 上传图文消息内的图片获取URL
    public function get_file_media_id($access_token, $type, $filename) {

        // 查询本地库
        $rt = $this->table(weixin_wxtable('media_id'))->where('file', md5($filename))->getRow();
        if ($rt) {
            return dr_return_data(1, 'ok', $rt);
        }
        $id = dr_get_file($filename, true);
        if (!$id) {
            return dr_return_data(0, '文件不存在');
        }
        $file = WRITEPATH.'temp/sync_'.md5($id).'.'.substr(strrchr($id, '.'), 1);;
        $c = dr_catcher_data($id);
        if (!$c) {
            return dr_return_data(0, '无法获取文件内容:'.$id);
        }
        $rt = file_put_contents($file, $c);
        if (!$rt) {
            return dr_return_data(0, '本地文件写入失败:'.$id);
        } elseif (!is_file($file)) {
            return dr_return_data(0, '本地文件不存在');
        }

        $rt = ihttp_request(
            'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.$access_token,
            [
                'type' => 'image',
                'media' => '@' . $file
            ]
        );
        if ($rt['code']) {
            // 更新到媒体表
            $save = [
                'file' => md5($filename),
                'url' => $rt['data']['url'],
                'media_id' => $rt['data']['media_id'],
            ];
            $this->table(weixin_wxtable('media_id'))->insert($save);
        }

        return $rt;
    }

    // 同步素材到服务器
    public function sync_content($access_token, $t, $return = 0) {

        if (!$t['media_id'] || $return) {
            // 图文素材
            $url = 'https://api.weixin.qq.com/cgi-bin/draft/add?access_token='.$access_token;
            $param = [
                'articles' => [

                ]
            ];
            $value = dr_string2array($t['content']);
            for ($i = 1; $i<=9; $i++) {
                if (!$value['title_'.$i]) {
                    break;
                }
                if (!$value['thumb_'.$i]) {
                    return dr_return_data(0, '素材['.$t['title'].'] 第'.$i.'个内容缺少封面图片');
                }
                $cache = [];
                $content = htmlspecialchars_decode($value['content_'.$i]);
                if (preg_match_all("/(src)=([\"|']?)([^ \"'>]+\.(gif|jpg|jpeg|png))\\2/i", $content, $imgs)) {
                    foreach ($imgs[3] as $image) {
                        if (!isset($cache[$image])) {
                            $tmp = WRITEPATH.'temp/sync_'.md5($image).'.'.substr(strrchr($image, '.'), 1);;
                            if (strpos($image, '/')  === 0 && is_file(WEBPATH.$image)) {
                                $file = file_get_contents(WEBPATH.$image);
                            } else {
                                $file = dr_catcher_data($image);
                            }
                            if ($file && file_put_contents($tmp, $file)) {
                                $cache[$image] = 1;
                                $rt = ihttp_request(
                                    'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token='.$access_token,
                                    [
                                        'media' => '@' . $tmp
                                    ]
                                );
                                // 更新到内容
                                $rt['code'] && $content = str_replace($image, $rt['data']['url'], $content);
                            }
                        }
                    }
                }
                $rt = $this->get_file_media_id($access_token, 'thumb', $value['thumb_'.$i]);
                if (!$rt['code']) {
                    $rt['msg'] = $value['thumb_'.$i].' - 附件上传失败：'.$rt['msg'];
                    return $rt;
                }

                $thumb_id = $rt['data']['media_id'];
                $param['articles'][] = [
                    "title" => $value['title_'.$i],
                    "thumb_media_id" => $thumb_id,
                    "author" => $value['author_'.$i],
                    "digest" => dr_strcut($value['description_'.$i], 50),
                    "content" => $content,
                    "show_cover_pic" => 1,
                    "content_source_url" => html_entity_decode($value['url_'.$i])
                ];
            }
            if (!count($param['articles'])) {
                return dr_return_data(0, '素材['.$t['title'].'] 资源信息为空无法同步');
            }
            $rt = wx_post_https_json_data($url, $param);
            if (!$rt['code']) {
                return $rt;
            }
            $media_id = $rt['data']['media_id'];
            if ($return) {
                return dr_return_data(1, $media_id);
            }
        } else {
            $media_id = $t['media_id'];
        }

        if (!$t['publish_id']) {
            // 发布内容
            $rt = wx_post_https_json_data(
                'https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token='.$access_token,
                [
                    'media_id' => $media_id
                ]
            );
            if (!$rt['code']) {
                $this->table(weixin_wxtable('content'))->update($t['id'], [
                    'media_id' => $media_id
                ]);
                return $rt;
            }
            // 存储
            $this->table(weixin_wxtable('content'))->update($t['id'], [
                'media_id' => $media_id,
                'publish_id' => $rt['data']['publish_id'],
            ]);
        } else {
            // 查询结果
            $rt = wx_post_https_json_data(
                'https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token='.$access_token,
                [
                    'publish_id' => $t['publish_id']
                ]
            );
            if (!$rt['code']) {
                return $rt;
            }
            $this->table(weixin_wxtable('content'))->update($t['id'], [
                'status' => $rt['data']['publish_status'],
                'article_id' => $rt['data']['article_id']
            ]);
        }

        return dr_return_data(1, 'ok');
    }

    // 高级群发
    public function sendall($groupid, $data)
    {

        $rt = weixin_get_access_token();
        if (!$rt['code']) {
            return $rt;
        }

        // 将内容转成为草稿箱
        $rs = $this->sync_content($rt['msg'], $data, 1);
        if (!$rs['code']) {
            return $rs;
        }

        $param = [
            'msgtype' => 'mpnews',
            'mpnews' => [
                'media_id' => $rs['msg']
            ],
        ];

        if ($groupid) {
            $param['filter'] = [
                'is_to_all' => false,
                'tag_id' => $groupid,
            ];
        } else {
            $param['filter'] = [
                'is_to_all' => true,
            ];
        }

        $rt = wx_post_https_json_data(
            'https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token='.$rt['msg'],
            $param
        );
        if (!$rt['code']) {
            return $rt;
        }

        return dr_return_data(1, 'ok');
    }

     // 客服群发 文本内容
    public function send_for_text($groupid, $data)
    {

        $param = [
            'msgtype' => 'text',
            'text' => [
                'content' => $data
            ],
        ];

        if ($groupid) {
            if (strlen($groupid) > 5) {
                // 指定粉丝
                $user = [
                    [
                        'openid' => $groupid,
                    ]
                ];
            } else {
                // 粉丝组
                $user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->where('`groupids` like "%\"'.$groupid.'\"%"')->getAll();
            }
        } else {
            // 全部粉丝
            $user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
        }

        if (!$user) {
            return dr_return_data(0, '48小时内互动的粉丝不存在');
        }

        return $this->_save_send_data($user, $param);
    }

    // 客服群发 内容模块
    public function send_for_module($dir, $ids) {

        $data = $this->table_site($dir)->where_in('id', $ids)->getAll(9);
        if (!$data) {
            return dr_return_data(0, '模块内容不存在');
        }

        $param = [
            'msgtype' => 'news',
            'news' => [
                'articles' => []
            ],
        ];
        foreach ($data as $t) {
            $param['news']['articles'][] = [
                "title" => $t['title'],
                "description" => $t['description'],
                "picurl" => dr_get_file($t['thumb'], true),
                "url" => dr_url_prefix($t['url'], $dir)
            ];
        }

        $user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
        if (!$user) {
            return dr_return_data(0, '粉丝信息不存在');
        }
        return $this->_save_send_data($user, $param);

    }

    // 客服群发 内容素材
    public function send_for_content($groupid, $data)
    {

        $param = [
            'msgtype' => 'mpnewsarticle',
            'mpnewsarticle' => [
                'article_id' => $data['article_id']
            ],
        ];

        if ($groupid) {
            if (strlen($groupid) > 5) {
                // 指定粉丝
                $user = [
                    [
                        'openid' => $groupid,
                    ]
                ];
            } else {
                // 粉丝组
                $user = $this->table(weixin_wxtable('user'))->where('groupid', $groupid)->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
            }
        } else {
            // 全部粉丝
            $user = $this->table(weixin_wxtable('user'))->where('subscribe>0 and subscribe_time > '.(SYS_TIME - 3600*48))->getAll();
        }

        if (!$user) {
            return dr_return_data(0, '48小时内互动的粉丝不存在');
        } elseif (!$param) {
            return dr_return_data(0, '未知的tid类别信息：'.$data['tid']);
        }

        return $this->_save_send_data($user, $param);
    }

    // 存储客服消息发送记录表
    private function _save_send_data($user, $param) {

        $id = (int)substr(SYS_TIME - rand(0, 9999), 0, 10);

        foreach ($user as $t) {
            $rt = $this->table(weixin_wxtable('send'))->insert([
                'cid' => $id,
                'openid' => $t['openid'],
                'status' => 0,
                'content' => dr_array2string($param)
            ]);
            if (!$rt['code']) {
                return $rt;
            }
        }

        return dr_return_data($id, 'ok');
    }

    // 存储客户端消息
    public function save_message($data)
    {

        $rt = $this->table(weixin_wxtable('message'))->insert([
            'tid' => $data['MsgType'],
            'openid' => $data['FromUserName'],
            'nickname' => '',
            'headimgurl' => '',
            'status' => 0,
            'content' => dr_array2string($data),
            'inputtime' => $data['CreateTime'],
        ]);
        if (!$rt['code']) {
            log_message('error', '微信消息存储失败：'.$rt['msg']);
        }

    }

    // 更新统计数据
    public function update_count_fans() {

        return $this->table(weixin_wxtable('count_fans'))->order_by('id desc')->getAll(10, 'date');

        $seven_days = array(
            date('Ymd', strtotime('-1 days')),
            date('Ymd', strtotime('-2 days')),
            date('Ymd', strtotime('-3 days')),
            date('Ymd', strtotime('-4 days')),
            date('Ymd', strtotime('-5 days')),
            date('Ymd', strtotime('-6 days')),
            date('Ymd', strtotime('-7 days')),
        );

        // 本周数据
        $week_stat_fans = $this->table(weixin_wxtable('count_fans'))->where_in('date', $seven_days)->getAll(0, 'date');
        $stat_update_yes = false;
        foreach ($seven_days as $sevens) {
            if (empty($week_stat_fans[$sevens]) || $week_stat_fans[$sevens]['cumulate'] <=0) {
                $stat_update_yes = true;
                break;
            }
        }

        if (empty($stat_update_yes)) {
            return $week_stat_fans;
        }

        $rt = weixin_get_access_token();
        if ($rt['code']) {
            $access_token = $rt['msg'];
            $url = 'https://api.weixin.qq.com/datacube/getusersummary?access_token='.$access_token;
            $rt = wx_post_https_json_data($url, [
                "begin_date" => date('Y-m-d', strtotime('-7 days')),
                "end_date" => date('Y-m-d', strtotime('-1 days')),
            ]);
            if ($rt['code']) {
                $summary = $rt['data'];
            }

            $url = 'https://api.weixin.qq.com/datacube/getusercumulate?access_token='.$access_token;
            $rt = wx_post_https_json_data($url, [
                "begin_date" => date('Y-m-d', strtotime('-7 days')),
                "end_date" => date('Y-m-d', strtotime('-1 days')),
            ]);
            if ($rt['code']) {
                $cumulate = $rt['data'];
            }

            $result = [];
            if (!empty($summary['list'])) {
                foreach ($summary['list'] as $row) {
                    $key = str_replace('-', '', $row['ref_date']);
                    $result[$key]['new'] = intval($result[$key]['new']) + $row['new_user'];
                    $result[$key]['cancel'] = intval($result[$key]['cancel']) + $row['cancel_user'];
                }
            }
            if (!empty($cumulate['list'])) {
                foreach ($cumulate['list'] as $row) {
                    $key = str_replace('-', '', $row['ref_date']);
                    $result[$key]['cumulate'] = $row['cumulate_user'];
                }
            }

            foreach ($result as $i => $t) {
                $this->table(weixin_wxtable('count_fans'))->replace([
                   'new' => (int)$t['new'],
                   'cancel' => (int)$t['cancel'],
                   'cumulate' => (int)$t['cumulate'],
                   'date' => $i,
                ]);
            }

            return $result;
        }

        return $week_stat_fans;
    }

    /**
     * 发送微信通知模板
     *
     * $uid 会员id
     * $id  微信模板id
     * $data    通知内容
     * $url 详细地址
     * $color   top颜色
     */
    public function send_template($uid, $id, $data, $url = '', $color = '') {

        $rt =  weixin_get_access_token();
        if (!$rt['code']) {
            return dr_return_data(0, $rt['msg']);
        }

        if (is_array($uid)) {
            $error = [];
            foreach ($uid as $u) {
                $oauth = $this->db->table('member_oauth')->where('uid', $u)->where('oauth', 'wechat')->get()->getRowArray();
                if (!$oauth) {
                    $error[] = 'uid（'.$u.'）未绑定账号';
                    continue;
                }
                $rs = wx_post_https_json_data('https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$rt['msg'],  [
                    'touser' => $oauth['oid'],
                    'template_id' => $id,
                    'url' => $url,
                    'topcolor' => $color,
                    'data' => $data,
                ]);
                if (!$rs['code']) {
                    $error[] = $rs['msg'];
                }
            }
            if (dr_count($error) == dr_count($uid)) {
                return dr_return_data(0, implode('；', $error));
            } else {
                return dr_return_data(1, '发送成功');
            }
        } else {
            $oauth = $this->db->table('member_oauth')->where('uid', $uid)->where('oauth', 'wechat')->get()->getRowArray();
            if (!$oauth) {
                return dr_return_data(0, 'uid（'.$uid.'）未绑定账号');
            }

            return wx_post_https_json_data('https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$rt['msg'],  [
                'touser' => $oauth['oid'],
                'template_id' => $id,
                'url' => $url,
                'topcolor' => $color,
                'data' => $data,
            ]);
        }

    }

    /**
     * 发送微信订阅通知
     *
     * $uid 会员id
     * $id  所需下发的订阅模板id
     * $data    通知内容
     * $url 详细地址
     */
    public function send_biz($uid, $id, $data, $url = '') {

        $oauth = $this->db->table('member_oauth')->where('uid', $uid)->where('oauth', 'wechat')->get()->getRowArray();
        if (!$oauth) {
            return dr_return_data(0, 'uid（'.$uid.'）未绑定账号');
        }

        $rt =  weixin_get_access_token();
        if (!$rt['code']) {
            return dr_return_data(0, $rt['msg']);
        }

        return wx_post_https_json_data('https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend?access_token='.$rt['msg'],  [
            'touser' => $oauth['oid'],
            'template_id' => $id,
            'page' => $url,
            'data' => $data,
        ]);
    }

    // 缓存
    public function cache($siteid = SITE_ID)
    {

        $table =  \Phpcmf\Service::M()->dbprefix('app_weixin');
        if (!\Phpcmf\Service::M()->is_table_exists($table)) {
            \Phpcmf\Service::M('table')->create_table(
                $table,
                [
                    'id' => 'int(10) NOT NULL AUTO_INCREMENT COMMENT \'id\'',
                    'name' => 'varchar(200) NOT NULL COMMENT \'公众号名称\'',
                ],
                [
                    'PRIMARY KEY (`id`)',
                ],
                '多公众号表'
            );
        }

        $mr = \Phpcmf\Service::M()->table('app_weixin')->get(1);
        if (!$mr) {
            \Phpcmf\Service::M()->table('app_weixin')->replace([
                'id' => 1,
                'name' => '默认公众号'
            ]);
        }

        $alls = $this->table('app_weixin')->getAll();
        $more_cache = [];
        foreach ($alls as $more) {
            $more_cache[$more['id']] = $more['name'];
            /////////////////////////
            $data = $this->table(weixin_wxtable('weixin', $more['id']))->getAll();

            $cache = [];
            if ($data) {
                foreach ($data as $t) {
                    $value = dr_string2array($t['value']);
                    $cache[$t['name']] = $value;
                }
            }

            $kws = [];
            $data = $this->table(weixin_wxtable('reply', $more['id']))->getAll();
            if ($data) {
                foreach ($data as $t) {
                    $arr = explode(',', $t['keyword']);
                    if ($arr) {
                        foreach ($arr as $kw) {
                            $kws[$kw] = $t['id'];
                        }
                    }
                }
                uksort($kws, function ($a, $b) {
                    return strlen($b) - strlen($a);
                });
            }
            \Phpcmf\Service::L('cache')->set_file('weixin-kws'.($more['id'] > 1 ? '_more_'.$more['id'] : ''), $kws);

            $table = $this->dbprefix(weixin_wxtable('template', $more['id']));
            if (!\Phpcmf\Service::M()->is_table_exists($table)) {
                \Phpcmf\Service::M('table')->create_table(
                    $table,
                    [
                        'id' => 'int(10) NOT NULL AUTO_INCREMENT COMMENT \'id\'',
                        'title' => 'varchar(200) NOT NULL COMMENT \'主题\'',
                        'groupid' => 'int(10) NOT NULL COMMENT \'发送标签组\'',
                        'counts' => 'int(10) NOT NULL COMMENT \'发送数\'',
                        'content' => 'text NOT NULL COMMENT \'消息内容\'',
                        'template' => 'varchar(200) NOT NULL COMMENT \'模板ID\'',
                        'url' => 'varchar(200) NOT NULL COMMENT \'url\'',
                        'color' => 'varchar(200) NOT NULL COMMENT \'主题颜色\'',
                        'inputtime' => 'int(10) NOT NULL COMMENT \'录入时间\'',
                    ],
                    [
                        'PRIMARY KEY (`id`)',
                        'KEY `inputtime` (`inputtime`)',
                    ],
                    '微信模板消息记录表'
                );
            }

            $table = $this->dbprefix(weixin_wxtable('user', $more['id']));
            \Phpcmf\Service::M()->query('UPDATE `'.$table.'` SET `subscribe`=`subscribe_time` where `subscribe`=1');

            $table = $this->dbprefix(weixin_wxtable('content', $more['id']));
            $t = \Phpcmf\Service::M('table');
            $m = \Phpcmf\Service::M();
            if (!$m->is_field_exists($table, 'nums')) {
                $t->add_field($table, 'nums', 'tinyint(2)', 'DEFAULT \'0\'', '');
            }
            if (!$m->is_field_exists($table, 'status')) {
                $t->add_field($table, 'status', 'tinyint(2)', 'DEFAULT \'0\'', '');
            }
            if (!$m->is_field_exists($table, 'publish_id')) {
                $t->add_field($table, 'publish_id', 'varchar(255)', 'DEFAULT \'\'', '');
            }
            if (!$m->is_field_exists($table, 'article_id')) {
                $t->add_field($table, 'article_id', 'varchar(255)', 'DEFAULT \'\'', '');
            }


            \Phpcmf\Service::L('cache')->set_file('weixin'.($more['id'] > 1 ? '_more_'.$more['id'] : ''), $cache);
            /// ////////////////////////
        }

        \Phpcmf\Service::L('cache')->set_file('app_weixin', count($more_cache) == 1 ? '' : $more_cache);

        return;
    }

}