<?php
/**
 * article and page model
 *
 * @package EMLOG
 * @link https://www.emlog.net
 */

class Order_Model {

    private $db;
    private $Parsedown;
    private $table;
    private $table_user;
    private $table_sort;

    public function __construct() {
        $this->db = Database::getInstance();
        $this->table = DB_PREFIX . 'order';
        $this->table_user = DB_PREFIX . 'user';
        $this->table_sort = DB_PREFIX . 'sort';
        $this->Parsedown = new Parsedown();
        $this->Parsedown->setBreaksEnabled(true); //automatic line wrapping
    }
    
    
    public function test($content){
        
        $tm = date('Y-m-d H:i:s', time());
        
        $sql = "insert into ". DB_PREFIX . "test (name, content, create_time) values ('test', '{$content}', '{$tm}')";
        
        $sql = rtrim($sql, ',');
        $this->db->query($sql);
    }

    /**
     * 获取待处理订单数量
     */
    public function getDcl() {
        $sql = "SELECT COUNT(*) AS total FROM {$this->table} where status = 1 and delete_time is null";
        $res = $this->db->once_fetch_array($sql);
        return $res['total'];
    }

    public function getTodayOrder() {
        $timestamp = time();
        $sql = "SELECT COUNT(*) AS total FROM {$this->table} where DATE(FROM_UNIXTIME({$timestamp})) = CURDATE() and delete_time is null and pay_time is not null";
        $res = $this->db->once_fetch_array($sql);
        return $res['total'];
    }

    public function getYesterdayOrder() {
        $timestamp = time();
        $sql = "SELECT COUNT(*) AS total FROM {$this->table} where DATE(FROM_UNIXTIME({$timestamp})) = CURDATE() - INTERVAL 1 DAY and delete_time is null and pay_time is not null";
        $res = $this->db->once_fetch_array($sql);
        return $res['total'];
    }

    public function getSevendayOrder() {

        $timestamp = time();
        $sql = "SELECT COUNT(*) AS total FROM {$this->table} where DATE(FROM_UNIXTIME({$timestamp})) BETWEEN CURDATE() - INTERVAL 6 DAY AND CURDATE() and delete_time is null and pay_time is not null";
        $res = $this->db->once_fetch_array($sql);
        return $res['total'];
    }

    /**
     * 获取子订单卡密
     */
    public function getOrderSdk($order_list_id) {
        $sql = "SELECT * from " . DB_PREFIX . "deliver WHERE order_list_id={$order_list_id}";
//        echo $sql;die;
        $res = $this->db->query($sql);
        $data = [];
        while ($row = $this->db->fetch_array($res)) {
            $data['sdk'][] = $row;
            $data['order_id'] = empty($data['order_id']) ? $row['order_id'] : $data['order_id'];
        }
        return $data;
    }

    /**
     * 创建主订单
     */
    public function addOrder($productData) {
        $kItem = $dItem = [];
        foreach ($productData as $key => $data) {
            $kItem[] = $key;
            $dItem[] = $data;
        }
        $field = implode(',', $kItem);
        $values = "'" . implode("','", $dItem) . "'";
        $this->db->query("INSERT INTO $this->table ($field) VALUES ($values)");
        return $this->db->insert_id();
    }
    /**
     * 创建子订单
     */
    public function addOrderList($insertData) {
        $kItem = $dItem = [];
        foreach ($insertData as $key => $data) {
            $kItem[] = $key;
            $dItem[] = $data;
        }
        $field = implode(',', $kItem);
        $values = "'" . implode("','", $dItem) . "'";
        $this->db->query("INSERT INTO " . DB_PREFIX . "order_list ($field) VALUES ($values)");
        return true;
    }

    /**
     * 获取产品sku信息
     */
    public function getSku($goods_id, $sku){
        $sql = "SELECT * FROM " . DB_PREFIX . "skus where goods_id={$goods_id} and sku='{$sku}'";
//        echo $sql;die;
        $res = $this->db->query($sql);
        $row = $this->db->fetch_array($res);


        $price = -1;
        if(LEVEL == -1){
            $price= $row['guest_price'] / 100;
        }else{
            $sql = "SELECT * FROM " . DB_PREFIX . "member_price where goods_id={$goods_id} and sku='{$sku}'";
            $member_price = $this->db->fetch_all($sql);
            foreach($member_price as $v){
                if($v['member_level'] == LEVEL && $row['sku'] == $v['sku']){
                    $price = $v['price'] / 100;
                }
            }
            $price = $price == -1 ? $row['user_price'] / 100 : $price;
        }


        $row['price'] = $price;
        return $row;
    }

    /**
     * 获取sku的规格属性
     */
    public function getSpecification($specification_ids){
        if (empty($specification_ids)) {
            return false;
        }
        $data = [];
        foreach($specification_ids as $val){
            $sql = "SELECT * FROM " . DB_PREFIX . "sku_attr where id={$val}";
            $res = $this->db->query($sql);
            $row = $this->db->fetch_array($res);
            $data[] = $row;
        }
//        d($data);
        return $data;
    }

    /**
     * 获取sku的规格属性值
     */
    public function getSpecificationValue($specification) {
        if (empty($specification)) {
            return false;
        }
        $specification = explode('-', $specification);
        $data = [];
        foreach($specification as $val){
            $sql = "SELECT * FROM " . DB_PREFIX . "sku_value where id={$val}";
            $res = $this->db->query($sql);
            $row = $this->db->fetch_array($res);
            $data[] = $row;
        }
//        d($data);
        return $data;
    }

    function delete($id){
        $timestamp = time();
        $sql = "UPDATE " . DB_PREFIX . "order set delete_time={$timestamp} where id=$id";
        $this->db->query($sql);
    }

    /**
     * 获取主订单信息
     */
    public function getOrderInfo($out_trade_no) {
        $sql = "SELECT * FROM $this->table WHERE out_trade_no='{$out_trade_no}'";
        $res = $this->db->query($sql);
        $row = $this->db->fetch_array($res);
        $row['amount'] /= 100;
        return $row;
    }
    public function getOrderInfoId($id) {
        $sql = "SELECT * FROM $this->table WHERE id={$id}";
        $res = $this->db->query($sql);
        $row = $this->db->fetch_array($res);
        return $row;
    }
    /**
     * 获取子订单信息
     */
    public function getOrderList($order_id) {
        $prefix = DB_PREFIX;
        $sql = <<<sql
                    SELECT 
                        ol.*, g.type 
                    FROM 
                        {$prefix}order_list as ol
                    LEFT JOIN
                        {$prefix}goods as g ON ol.goods_id=g.id
                    WHERE 
                        ol.order_id={$order_id}
sql;

        $res = $this->db->query($sql);
        $data = [];
        while ($row = $this->db->fetch_array($res)) {
            $data[] = $row;
        }
        return $data;
    }

    /**
     * 支付完成后，给订单发货
     */
    public function deliver($order_id){
        $timestamp = time();
        $order_list = $this->getOrderList($order_id);
        $stock_table = DB_PREFIX . 'stock'; // 库存表
        $order_talbe = DB_PREFIX . 'order'; // 订单表
        $goods_table = DB_PREFIX . 'goods';
        $goodsModel = new Goods_Model();

        $order = $this->getOrderInfoId($order_id);

        $plugin_deliver = '';

        foreach($order_list as $val){ // 循环发货 - 子订单
            $sku = (empty($val['sku']) || $val['sku'] == '0') ? '0' : $val['sku'] ;
            $goods = $goodsModel->getOneGoodsForHome($val['goods_id']);
            $plugin_goods_name = $goods['title'];
            $plugin_goods_type = $goods['type'];
            $plugin_sku = $val['attr_spec'];
            $plugin_attach_user = json_decode($val['attach_user']);
            $plugin_quantity = $val['quantity'];
            $plugin_goods_price = $val['unit_price'] / 100;

            if($goods['type'] == 'guding'){ // 固定卡密
                $sql = <<<sql
                    SELECT
                        *
                    FROM 
                        {$stock_table}
                    WHERE
                        goods_id = {$val['goods_id']} AND sku = '{$sku}'
                    ORDER BY 
                        create_time asc
                    LIMIT 
                        0, 1
sql;
//                echo $sql; die;
                $result = $this->db->query($sql); // 查询出库存表里的卡密

                $stock = $this->db->fetch_array($result);

//d($stock);die;
                // 将查询出的卡密写入到发货表里
                $insert_deliver = [
                    'order_id' => $order_id,
                    'order_list_id' => $val['id'],
                    'content' => $stock['content'],
                    'create_time' => $timestamp
                ];
                $this->db->add('deliver', $insert_deliver);


                // 扣除库存表中的库存数量
                $new_quantity = $stock['quantity'] - $val['quantity'];
                $new_quantity = $new_quantity < 0 ? 0 : $new_quantity;

                $sql = "UPDATE 
                            {$stock_table}
                        SET
                            quantity = {$new_quantity}
                        WHERE 
                            goods_id={$val['goods_id']} and sku='{$sku}'";
                $this->db->query($sql);

                // 修改订单状态
                $sql = <<<sql
                        UPDATE 
                            {$order_talbe}
                        SET
                            status = 2
                        WHERE 
                            id = {$order_id}
sql;


                $this->db->query($sql);

            }

            if($goods['type'] == 'duli'){ // 独立卡密
                $kami_order = Option::get('kami_order');
                $kami_order = empty($kami_order) ? 'asc' : $kami_order;

                // 构建查询排序条件
                switch($kami_order) {
                    case 'asc':
                        $orderSql = 'ORDER BY id asc';
                        break;
                    case 'desc':
                        $orderSql = 'ORDER BY id desc';
                        break;
                    default:
                        $orderSql = 'ORDER BY RAND()';
                }

                // 计算总数量和批次信息
                $totalQuantity = $val['quantity'];
                $batchSize = 1000; // 每批次处理数量，可根据内存情况调整
                $totalBatches = ceil($totalQuantity / $batchSize);
                $processed = 0;

                $pluginDeliver = [];

                // 分批次处理
                for ($batch = 0; $batch < $totalBatches; $batch++) {
                    // 计算当前批次处理数量
                    $currentBatchSize = min($batchSize, $totalQuantity - $processed);

                    // 构建当前批次的查询SQL
                    $sql = "SELECT id, content, goods_id FROM  {$stock_table} 
                WHERE goods_id = {$val['goods_id']} AND sku = '{$sku}' 
                {$orderSql} LIMIT {$currentBatchSize}";

                    $result = $this->db->query($sql); // 查询当前批次的卡密

                    // 准备当前批次的数据容器
                    $deliverValues = [];
                    $stockIds = [];

                    // 收集当前批次数据
                    while($row = $this->db->fetch_array($result)){
                        $escapedContent = $row['content'];
                        $deliverValues[] = "({$order_id}, {$val['id']}, '{$escapedContent}', {$timestamp})";
                        $stockIds[] = $row['id'];
                        $pluginDeliver[] = $row['content'];
                    }

                    // 批量插入当前批次发货记录
                    if(!empty($deliverValues)){
                        $insertSql = "INSERT INTO " . DB_PREFIX . "deliver 
                         (order_id, order_list_id, content, create_time) 
                         VALUES " . implode(',', $deliverValues);
                        $this->db->query($insertSql);
                    }

                    // 批量删除当前批次库存记录
                    if(!empty($stockIds)){
                        $idsStr = implode(',', $stockIds);
                        $deleteSql = "DELETE FROM " . DB_PREFIX . "stock WHERE id IN ({$idsStr})";
                        $this->db->query($deleteSql);
                    }

                    // 更新已处理数量
                    $processed += $currentBatchSize;

                    // 释放当前批次内存
                    unset($deliverValues, $stockIds, $result, $row);
                }


                // 更新订单状态
                $sql = <<<sql
            UPDATE 
                {$order_talbe}
            SET
                status = 2
            WHERE 
                id = '{$order_id}'
sql;
                $this->db->query($sql);
            }


            if($goods['type'] == 'xuni'){ // 虚拟服务类型

                $sql = <<<sql
                    SELECT
                        *
                    FROM 
                        {$stock_table}
                    WHERE
                        goods_id = {$val['goods_id']} AND sku = '{$sku}'
                    ORDER BY 
                        create_time asc
                    LIMIT 
                        0, 1
sql;
//                echo $sql; die;
                $result = $this->db->query($sql); // 查询出库存表里的卡密

                $row = $this->db->fetch_array($result);

                $sql = <<<sql
                        UPDATE 
                            {$stock_table}
                        SET
                            quantity = quantity - 1
                        WHERE 
                            goods_id = {$val['goods_id']} AND sku = '{$sku}'
sql;
                $this->db->query($sql);
                $sql = <<<sql
                        UPDATE 
                            {$order_talbe}
                        SET
                            status = 1
                        WHERE 
                            id = '{$order_id}'
sql;
                $this->db->query($sql);
            }

            if($goods['type'] == 'post'){ // 自定义访问url
                $sql = <<<sql
                    SELECT
                        *
                    FROM 
                        {$stock_table}
                    WHERE
                        goods_id = {$val['goods_id']} AND sku = '{$sku}'
                    ORDER BY 
                        create_time asc
                    LIMIT 
                        0, 1
sql;


                $stock = $this->db->once_fetch_array($sql);

                $sql = "select * from " . DB_PREFIX . "skus where goods_id={$val['goods_id']} and sku='{$sku}'";
                $skus = $this->db->once_fetch_array($sql);



                // 初始化cURL会话
                $ch = curl_init();

                curl_setopt($ch, CURLOPT_URL, $skus['post_url']);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
                curl_setopt($ch, CURLOPT_POST, true);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(json_decode($val['attach_user'], true)));
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 不验证SSL证书
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
                $response = curl_exec($ch);
                if (curl_errno($ch)) {
                    echo 'Curl error: ' . curl_error($ch);
                }
                curl_close($ch);
                $res = json_decode($response, true);
                // 处理响应
                if ($res === false) {
                    $sql = <<<sql
                        UPDATE 
                            {$order_talbe}
                        SET
                            status = 2  -- 2=已完成， 1=待处理
                        WHERE 
                            id = '{$order_id}'
sql;
                    $this->db->query($sql);
                } else {
                    $sql = <<<sql
                        UPDATE 
                            {$order_talbe}
                        SET
                            status = 1  -- 2=已完成， 1=待处理
                        WHERE 
                            id = '{$order_id}'
sql;
                    $this->db->query($sql);
                }
                $orderModel = new Order_Model();
                $orderModel->handDeliver($val['id'], '处理完成');

                $plugin_deliver .= '处理完成' . '<br/>';


                $sql = <<<sql
                        UPDATE 
                            {$stock_table}
                        SET
                            quantity = quantity - 1
                        WHERE 
                            goods_id = {$val['goods_id']} AND sku = '{$sku}'
sql;
                $this->db->query($sql);


            }

            // 更新商品销量
            $sql = "update {$goods_table} set sales = sales + {$val['quantity']} where id = {$val['goods_id']}";
            $this->db->execute($sql);

        }

        if($plugin_goods_type == 'duli'){
            $plugin_goods_type = '独立卡密';
        }
        if($plugin_goods_type == 'xuni'){
            $plugin_goods_type = '服务类型';
        }
        if($plugin_goods_type == 'guding'){
            $plugin_goods_type = '固定卡密';
        }

        if(empty($plugin_deliver)){
            $sql = "select * from " . DB_PREFIX . "deliver where order_id={$order_id} limit 10";
            $res = $this->db->fetch_all($sql);
            foreach($res as $val){
                $plugin_deliver .= $val['content'] . "\n";
            }
        }

        $sql = "select * from " . DB_PREFIX . "order_required where order_id={$order_id} and type='email' limit 1";
        $res = $this->db->once_fetch_array($sql);
        if($res){
            $order['email'] = $res['content'];
        }

        $plugin_data = [
            'out_trade_no' => $order['out_trade_no'], // 订单号
            'client_ip' => $order['client_ip'], // 下单IP
            'order_amount' => $order['amount'] / 100, // 订单总金额
            'create_time' => date('Y-m-d H:i:s', $order['create_time']), // 下单时间
            'payment' => $order['payment'], // 支付方式
            'pay_time' => date('Y-m-d H:i:s', $order['pay_time']), // 支付时间
            'password' => $order['pwd'], // 查单密码
            'goods_name' => $plugin_goods_name, // 商品名称
            'goods_type' => $plugin_goods_type, // 商品类型
            'sku' => $plugin_sku, // sku
            'attach_user' => $plugin_attach_user, // 附加选项
            'quantity' => $plugin_quantity, // 购买数量
            'goods_unit_price' => $plugin_goods_price, // 商品单价
            'deliver_content' => $plugin_deliver, // 发乎内容
            'order' => $order,
        ];


//        if($order['pay_plugin'] != 'payment'){
            $userModel = new User_Model();
            $userModel->expendInc($order['user_id'], $order['amount'] / 100);
//        }


        doAction('deliver_after', $plugin_data);


        return true;
    }

    /**
     * 更新订单的支付状态
     */
	public function updateOrderPayStatus($order_id, $data){
		$Item = [];
		foreach ($data as $key => $var) {
		    $Item[] = "$key=$var";
		}
		$upStr = implode(',', $Item);
		$sql = "UPDATE $this->table SET $upStr WHERE id = {$order_id}";
// 		echo $sql;die;
		return $this->db->execute("UPDATE $this->table SET $upStr WHERE id = {$order_id}");
	}

    /**
     * 修改主订单
     */
    public function updateOrderInfo($out_trade_no, $data) {
        $Item = [];
        foreach ($data as $key => $var) {
            $Item[] = "$key='$var'";
        }
        $upStr = implode(',', $Item);
        return $this->db->query("UPDATE $this->table SET $upStr WHERE out_trade_no = {$out_trade_no}");
    }

    /**
     * 虚拟服务，手动发货
     */
    public function handDeliver($order_id, $remark) {
        $Item = [];
        $data = [
            'status' => 2,
            'device' => $remark,
            'service_status' => 1
        ];
        foreach ($data as $key => $var) {
            $Item[] = "$key='$var'";
        }
        $upStr = implode(',', $Item);
        return $this->db->query("UPDATE $this->table SET $upStr WHERE id = {$order_id}");
    }

    /**
     * 获取订单总数
     */
    public function getOrderNum($where) {
        $w = "";
        $prefix = DB_PREFIX;
        if(!empty($where['email_username'])){
            $email_username = $where['email_username'];
            $w .= " and (u.email like  CONCAT('%', '{$email_username}', '%') or u.username like  CONCAT('%', '{$email_username}', '%') or u.nickname like  CONCAT('%', '{$email_username}', '%') or u.tel like  CONCAT('%', '{$email_username}', '%'))";
        }

        if(!empty($where['out_trade_no'])){
            $out_trade_no = $where['out_trade_no'];
            $w .= " and (o.out_trade_no like  CONCAT('%', '{$out_trade_no}', '%') or o.up_no like  CONCAT('%', '{$out_trade_no}', '%'))";
        }
        if(!empty($where['goods_title'])){
            $goods_title = $where['goods_title'];
            $w .= " and g.title like  CONCAT('%', '{$goods_title}', '%')";
        }
        if(!empty($where['client_ip'])){
            $client_ip = $where['client_ip'];
            $w .= " and o.client_ip like  CONCAT('%', '{$client_ip}', '%')";
        }
        if(!empty($where['order_required'])){
            $order_required = $where['order_required'];
            $w .= " and orq.content like  CONCAT('%', '{$order_required}', '%')";
        }



        $data = $this->db->once_fetch_array("SELECT 
                            count(DISTINCT o.id) as total 
                        FROM 
                            {$this->table} as o
                        LEFT JOIN {$prefix}user as u on o.user_id=u.uid
                        LEFT JOIN {$prefix}order_list as ol on o.id=ol.order_id
                        LEFT JOIN {$prefix}goods g on g.id=ol.goods_id
                        LEFT JOIN {$prefix}order_required as orq on o.id=orq.order_id
                        WHERE 
                            o.delete_time IS NULL {$w}
                            ");
        return $data['total'];
    }

    public function getOrderForAdmin($start, $limit, $where) {

        $prefix = DB_PREFIX;

        $w = "";

        if(!empty($where['email_username'])){
            $email_username = $where['email_username'];
            $w .= " and (u.email like  CONCAT('%', '{$email_username}', '%') or u.username like  CONCAT('%', '{$email_username}', '%') or u.nickname like  CONCAT('%', '{$email_username}', '%') or u.tel like  CONCAT('%', '{$email_username}', '%'))";
        }

        if(!empty($where['out_trade_no'])){
            $out_trade_no = $where['out_trade_no'];
            $w .= " and (o.out_trade_no like  CONCAT('%', '{$out_trade_no}', '%') or o.up_no like  CONCAT('%', '{$out_trade_no}', '%'))";
        }
        if(!empty($where['goods_title'])){
            $goods_title = $where['goods_title'];
            $w .= " and g.title like  CONCAT('%', '{$goods_title}', '%')";
        }
        if(!empty($where['client_ip'])){
            $client_ip = $where['client_ip'];
            $w .= " and o.client_ip like  CONCAT('%', '{$client_ip}', '%')";
        }
        if(!empty($where['order_required'])){
            $order_required = $where['order_required'];
            $w .= " and orq.content like  CONCAT('%', '{$order_required}', '%')";
        }




        $sql = <<<sql
                        SELECT 
                            o.* , u.email user_email, u.tel user_tel, u.nickname user_nickname 
                        FROM 
                            {$this->table} as o
                        LEFT JOIN {$prefix}user as u on o.user_id=u.uid
                        LEFT JOIN {$prefix}order_list as ol on o.id=ol.order_id
                        LEFT JOIN {$prefix}goods g on g.id=ol.goods_id
                        LEFT JOIN {$prefix}order_required as orq on o.id=orq.order_id
                        WHERE 
                            o.delete_time IS NULL {$w} 
                        GROUP BY 
                            o.id 
                        ORDER BY 
                            o.id desc 
                        limit 
                            {$start}, {$limit}
sql;
//        echo $sql;die;
        $res = $this->db->query($sql);

        $order_ids = [];
        $data = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['status'] = orderStatusText($row['status']);
            $row['amount'] /= 100;
            $row['email'] = empty($row['email']) ? '无' : $row['email'];
            $row['pwd'] = empty($row['pwd']) ? '无' : $row['pwd'];
            $row['tel'] = empty($row['tel']) ? '无' : $row['tel'];
            $row['up_no'] = empty($row['up_no']) ? '无' : $row['up_no'];
            $row['user_nickname'] = $row['user_id'] == 0 ? '游客身份' : $row['user_nickname'];
            

            $data[] = $row;
            $order_ids[] = $row['id'];
        }
        if(empty($data)) {
            return $data;
        }
        $order_ids = array_unique($order_ids);
        $order_ids = implode(',', $order_ids);

        $prefix = DB_PREFIX;
        $sql = <<<sql
                SELECT
                    ol.*, g.title, g.type, g.cover
                FROM
                    {$prefix}order_list as ol
                LEFT JOIN
                    {$prefix}goods as g ON ol.goods_id = g.id
                WHERE
                    ol.order_id IN ($order_ids) 
sql;
//        echo $sql;die;
        $order_list = [];
//        echo $order_ids;die;

        $res = $this->db->query($sql);
        while($row = $this->db->fetch_array($res)){

            foreach($data as $key => $val){
                if($val['id'] == $row['order_id']){
                    $row['goods_url'] = Url::log($row['goods_id']);
//                    var_dump($row['attach_user']);
                    $row['attach_user'] = empty($row['attach_user']) ? [] : json_decode($row['attach_user'], true);
                    $row['unit_price'] /= 100;
                    $attach_user = '';
//                    d($row);
                    foreach($row['attach_user'] as $k => $v){
                        $attach_user .= $k . '：' . $v . '；';
                    }
                    $row['attach_user'] = empty($attach_user) ? '无' : $attach_user;
                    $row['attr_spec'] = empty($row['attr_spec']) ? '默认规格' : $row['attr_spec'];
                    $data[$key]['list'][] = $row;
                    $row['attach_user'] = '';
                }
            }
        }

//        d($data);die;


        return $data;
    }



    /**
     * 获取订单总数
     */
    public function getUserOrderNum() {

        $data = $this->db->once_fetch_array("SELECT COUNT(*) AS total FROM $this->table where delete_time is null and user_id=" . UID . " GROUP BY id");
        if(empty($data)){
            return 0;
        }
        return $data['total'];
    }


    public function getUserOrderForHome($page = 1) {
        $perpage_num = Option::get('admin_article_perpage_num');
        $perpage_num = $perpage_num ? $perpage_num : 10;

        $start_limit = !empty($page) ? ($page - 1) * $perpage_num : 0;
        $limit = "$start_limit, " . $perpage_num;
        $prefix = DB_PREFIX;
        $sql = "
                        SELECT 
                            o.* 
                        FROM 
                            {$this->table} as o
                        WHERE 
                            o.delete_time IS NULL and user_id=" . UID . " 
                        GROUP BY 
                            o.id 
                        ORDER BY 
                            o.id desc 
                        LIMIT 
                            $limit";
        $res = $this->db->query($sql);

        $order_ids = "";
        $data = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['status'] = orderStatusText($row['status']);
            $row['amount'] /= 100;

            $data[] = $row;
            $order_ids .= $row['id'] . ",";
        }
        if(empty($data)) {
            return $data;
        }
        $order_ids = rtrim($order_ids, ",");
        $prefix = DB_PREFIX;
        $sql = <<<sql
                SELECT
                    ol.*, g.title, g.type, g.cover
                FROM
                    {$prefix}order_list as ol
                LEFT JOIN
                    {$prefix}goods as g ON ol.goods_id = g.id
                WHERE
                    ol.order_id IN ($order_ids)
sql;
        $order_list = [];
//        echo $order_ids;die;
//        echo $sql;die;
        $res = $this->db->query($sql);
        while($row = $this->db->fetch_array($res)){
            foreach($data as $key => $val){
                if($val['id'] == $row['order_id']){
                    $row['goods_url'] = Url::goods($row['goods_id']);
                    $data[$key]['list'][] = $row;
                }
            }
        }

//        d($data);die;


        return $data;
    }


    public function getYoukeOrderNum($pwd) {
        $prefix = DB_PREFIX;
        $sql = "SELECT COUNT(*) AS total FROM $this->table as o left join {$prefix}order_required as rq on o.id=rq.order_id where delete_time is null and (up_no='{$pwd}' or out_trade_no='{$pwd}' || pwd='{$pwd}' || rq.content='{$pwd}') GROUP BY o.id ";

        $data = $this->db->once_fetch_array($sql);
        return $data['total'];
    }


    public function getYoukeOrderForHome($page = 1, $pwd = '') {
        $perpage_num = Option::get('admin_article_perpage_num');
        $perpage_num = $perpage_num ? $perpage_num : 10;

        $start_limit = !empty($page) ? ($page - 1) * $perpage_num : 0;
        $limit = "$start_limit, " . $perpage_num;
        $prefix = DB_PREFIX;

        $where = "(o.up_no='{$pwd}' or o.out_trade_no='{$pwd}' || o.pwd='{$pwd}' || rq.content='{$pwd}')";

        $sql = "
                        SELECT 
                            o.* 
                        FROM 
                            {$this->table} as o
                        LEFT JOIN {$prefix}order_required as rq on o.id=rq.order_id
                        WHERE 
                            o.delete_time IS NULL and {$where} 
                        GROUP BY 
                            o.id 
                        ORDER BY 
                            o.id desc 
                        LIMIT 
                            $limit";
        $res = $this->db->query($sql);

//        d($res);die;

        $order_ids = "";
        $data = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['status'] = orderStatusText($row['status']);
            $row['amount'] /= 100;

            $data[] = $row;
            $order_ids .= $row['id'] . ",";
        }
        if(empty($data)) {
            return $data;
        }
        $order_ids = rtrim($order_ids, ",");
        $prefix = DB_PREFIX;
        $sql = <<<sql
                SELECT
                    ol.*, g.title, g.type, g.cover
                FROM
                    {$prefix}order_list as ol
                LEFT JOIN
                    {$prefix}goods as g ON ol.goods_id = g.id
                WHERE
                    ol.order_id IN ($order_ids)
sql;
        $order_list = [];
//        echo $order_ids;die;
//        echo $sql;die;
        $res = $this->db->query($sql);
        while($row = $this->db->fetch_array($res)){
            foreach($data as $key => $val){
                if($val['id'] == $row['order_id']){
                    $row['goods_url'] = Url::goods($row['goods_id']);
                    $data[$key]['list'][] = $row;
                }
            }
        }

//        d($data);die;


        return $data;
    }
















    public function getCount($uid = UID) {
        $sql = sprintf("SELECT count(*) as num FROM $this->table WHERE author=%d AND type='%s'", $uid, 'blog');
        $res = $this->db->once_fetch_array($sql);
        return $res['num'];
    }

    /**
     * Gets the number of articles for the specified condition
     *
     * @param int $spot 0:homepage 1:admin
     * @param string $hide
     * @param string $condition
     * @param string $type
     * @return int
     */
    public function getProductNum($hide = 'n', $condition = '', $type = 'product', $spot = 0) {
        $hide_state = $hide ? "and hide='$hide'" : '';

        if ($spot == 0) {
            $now = time();
            $date_state = "and date<=$now";
            $check_state = "and checked='y'";
            $author = '';
        } else {
            $date_state = '';
            $check_state = '';
            $author = User::haveEditPermission() ? '' : 'and author=' . UID;
        }

        $data = $this->db->once_fetch_array("SELECT COUNT(*) AS total FROM $this->table WHERE type='$type' $date_state $hide_state $check_state $author $condition");
        return $data['total'];
    }

    public function getPostCountByUid($uid, $time = 0) {
        $date = '';
        if ($time) {
            $date = "and date > $time";
        }

        $data = $this->db->once_fetch_array("SELECT COUNT(*) AS total FROM $this->table WHERE type='blog' and author=$uid $date");
        return $data['total'];
    }

    public function getOneProductForAdmin($blogId) {
        $author = User::haveEditPermission() ? '' : 'AND author=' . UID;
        $sql = "SELECT * FROM $this->table WHERE id=$blogId $author";
        $res = $this->db->query($sql);
        if ($this->db->affected_rows() < 1) {
            emMsg('权限不足！', './');
        }
        $row = $this->db->fetch_array($res);
        if ($row) {
            $row['title'] = htmlspecialchars($row['title']);
            $row['content'] = htmlspecialchars($row['content']);
            $row['password'] = htmlspecialchars($row['password']);
            $row['template'] = !empty($row['template']) ? htmlspecialchars(trim($row['template'])) : 'page';
            return $row;
        }
        return false;
    }

    public function getProductSpecificationForAdmin($goods_id){

        $sql = "SELECT * FROM $this->table WHERE id=$goods_id";
        $res = $this->db->query($sql);
        $product = $this->db->fetch_array($res);
        $sql = "SELECT * FROM `" . DB_PREFIX . "product_specification` where goods_id={$goods_id}";
        $result = $this->db->query($sql);
        $data = [];

        while ($row = $this->db->fetch_array($result)) {
            if($product['is_sku']){
                $data["skus[{$row['specification']}][price]"] = $row['price'] / 100;
                $data["skus[{$row['specification']}][market_price]"] = $row['market_price'] / 100;
                $data["skus[{$row['specification']}][cost_price]"] = $row['cost_price'] / 100;
                $data["skus[{$row['specification']}][stock]"] = $row['stock'];
            }else{
                $data['price'] = $row['price'] / 100;
                $data['market_price'] = $row['market_price'] / 100;
                $data['cost_price'] = $row['cost_price'] / 100;
                $data['stock'] = $row['stock'];
            }
        }
        return $data;
    }

    public function getDetail($blogId) {
        if (empty($blogId)) {
            return false;
        }
        $sql = "SELECT t1.*, t2.sid, t2.sortname, t2.alias as sort_alias FROM $this->table t1 LEFT JOIN $this->table_sort t2 ON t1.sortid=t2.sid WHERE t1.id=$blogId";
        $res = $this->db->query($sql);
        $row = $this->db->fetch_array($res);
        if ($row) {
            return $row;
        }
        return false;
    }

    public function getDetails($blogIds) {
        if (empty($blogIds) || !is_array($blogIds)) {
            return false;
        }
        $blogIdsString = implode(',', $blogIds);
        $sql = "SELECT t1.*, t2.sid, t2.sortname, t2.alias as sort_alias FROM $this->table t1 LEFT JOIN $this->table_sort t2 ON t1.sortid=t2.sid WHERE t1.id IN ($blogIdsString)";
        $res = $this->db->query($sql);
        $rows = array();
        while ($row = $this->db->fetch_array($res)) {
            $rows[] = $row;
        }
        return $rows;
    }

    /**
     * get single article
     * @param $blogId
     * @param bool $ignoreHide 忽略隐藏状态
     * @param bool $ignoreChecked 忽略审核状态
     * @return array|false
     */
    public function getOneProductForHome($blogId, $ignoreHide = false, $ignoreChecked = false) {
        $hide = $ignoreHide ? "" : "AND hide='n'";
        $checked = $ignoreChecked ? "" : "AND checked='y'";

        $sql = "SELECT * FROM $this->table WHERE id=$blogId $hide $checked";
        $res = $this->db->query($sql);
        $row = $this->db->fetch_array($res);

        if (!$row) {
            return false;
        }

        $sql = "SELECT * FROM " . DB_PREFIX . "product_specification WHERE goods_id=$blogId";
        $res = $this->db->query($sql);
        $product_specification = [];
        while ($product_specification_row = $this->db->fetch_array($res)) {
            $product_specification[] = $product_specification_row;
        }

        $specification_value_ids = explode('-', $product_specification[0]['specification']);
        $sql = "SELECT * FROM " . DB_PREFIX . "specification_value WHERE id IN (" . implode(',', $specification_value_ids) . ");";
        $res = $this->db->query($sql);
        $specification_value = [];
        while ($specification_row = $this->db->fetch_array($res)) {
            $specification_value[] = $specification_row;
        }
        $specification_ids = array_column($specification_value, 'specification_id');
        $sql = "SELECT * FROM " . DB_PREFIX . "specification WHERE id IN (" . implode(',', $specification_ids) . ");";
        $res = $this->db->query($sql);
        $specification = [];
        while ($specification_row = $this->db->fetch_array($res)) {
            $specification[] = $specification_row;
        }
        $specification_attr = [];
//        d($product_specification);
        foreach($specification as $key => $val){

            $specification[$key]['attr'] = [];
            foreach($product_specification as $k => $v){

                $product_specification[$k]['stock'] = (int)$v['stock'];

                $temp = explode('-', $v['specification']);
                if(!keyValueExistsInArray($specification[$key]['attr'], 'id', $temp[$key])){
                    $sql = "SELECT * FROM " . DB_PREFIX . "specification_value WHERE id={$temp[$key]}";
                    $res = $this->db->query($sql);
                    $value_temp = $this->db->fetch_array($res);
                    $specification[$key]['attr'][] = [
                        'id' => $temp[$key],
                        'name' => $value_temp['name']
                    ];
                }
            }
            $specification_attr[] = array_column($specification[$key]['attr'], 'id');
        }
        $product_specification = array_column($product_specification, null, 'specification');
        foreach($product_specification as $key => $val){
            if($val['stock'] <= 0){
                unset($product_specification[$key]);
            }
        }

//        d($specification_attr);
//        d($product_specification);
//        d($specification);





        return [
            'log_title'    => htmlspecialchars($row['title']),
            'timestamp'    => $row['date'],
            'date'         => $row['date'],
            'logid'        => (int)$row['id'],
            'sortid'       => (int)$row['sortid'],
            'type'         => $row['type'],
            'author'       => $row['author'],
            'log_cover'    => $row['cover'] ? getFileUrl($row['cover']) : '',
            'log_content'  => $this->Parsedown->text($row['content']),
            'views'        => (int)$row['views'],
            'comnum'       => (int)$row['comnum'],
            'top'          => $row['top'],
            'sortop'       => $row['sortop'],
            'hide'         => $row['hide'],
            'checked'      => $row['checked'],
            'attnum'       => (int)$row['attnum'],
            'allow_remark' => Option::get('iscomment') == 'y' ? $row['allow_remark'] : 'n',
            'password'     => $row['password'],
            'template'     => $row['template'],
            'link'         => $row['link'],
            'tags'         => $row['tags'],
            'specification' => $specification,
            'specification_attr' => $specification_attr,
            'specification_attr_json' => json_encode($specification_attr),
            'product_specification' => $product_specification,
            'product_specification_json' => json_encode($product_specification)
        ];
    }

    public function getProductForAdmin($condition = '', $hide_state = '', $page = 1, $type = 'product') {
        $perpage_num = Option::get('admin_article_perpage_num');
        $start_limit = !empty($page) ? ($page - 1) * $perpage_num : 0;
        $author = User::haveEditPermission() ? '' : 'and author=' . UID;
        $hide_state = $hide_state ? "and hide='$hide_state'" : '';
        $limit = "LIMIT $start_limit, " . $perpage_num;
        $sql = "SELECT * FROM $this->table WHERE type='$type' $author $hide_state $condition $limit";
        $res = $this->db->query($sql);
        $logs = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['timestamp'] = $row['date'];
            $row['date'] = date("Y-m-d H:i", $row['date']);
            $row['title'] = !empty($row['title']) ? htmlspecialchars($row['title']) : '无标题';
            $logs[] = $row;
        }
        return $logs;
    }

    public function getProductsForHome($condition = '', $page = 1, $perPageNum = 10) {
        $start_limit = !empty($page) ? ($page - 1) * $perPageNum : 0;
        $limit = $perPageNum ? "LIMIT $start_limit, $perPageNum" : '';
        $now = time();
        $sql = "SELECT * FROM $this->table WHERE type='product' and hide='n' and checked='y' and date<= $now $condition $limit";
        $res = $this->db->query($sql);
        $logs = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['log_title'] = htmlspecialchars(trim($row['title']));
            $row['log_cover'] = $row['cover'] ? getFileUrl($row['cover']) : '';
            $row['log_url'] = Url::log($row['id']);
            $row['logid'] = $row['id'];
            $cookiePassword = isset($_COOKIE['em_logpwd_' . $row['id']]) ? addslashes(trim($_COOKIE['em_logpwd_' . $row['id']])) : '';
            if (!empty($row['password']) && $cookiePassword != $row['password']) {
                $row['excerpt'] = '<p>[该文章已加密，请点击标题输入密码访问]</p>';
            }

            $row['log_description'] = $this->Parsedown->text(empty($row['excerpt']) ? $row['content'] : $row['excerpt']);
            $row['attachment'] = '';
            $row['tag'] = '';
            $row['tbcount'] = 0;
            $logs[] = $row;
        }
        return $logs;
    }

    /**
     * get rss article list
     */
    public function getLogsForRss($perPageNum = 10) {
        if ($perPageNum <= 0) {
            return [];
        }
        $now = time();
        $date_state = "and date<=$now";
        $sql = "SELECT *, t1.password as pwd FROM $this->table t1 LEFT JOIN $this->table_user t2 ON t1.author=t2.uid WHERE t1.hide='n' and t1.checked='y' and t1.type='blog' $date_state ORDER BY t1.date DESC limit 0," . $perPageNum;
        $result = $this->db->query($sql);
        $d = [];
        while ($re = $this->db->fetch_array($result)) {
            $re['id'] = $re['id'];
            $re['title'] = htmlspecialchars($re['title']);
            $re['content'] = $this->Parsedown->text($re['content']);
            if (!empty($re['pwd'])) {
                $re['content'] = '<p>[该文章已设置加密]</p>';
            } elseif (Option::get('rss_output_fulltext') == 'n') {
                if (!empty($re['excerpt'])) {
                    $re['content'] = $re['excerpt'];
                } else {
                    $re['content'] = extractHtmlData($re['content'], 330);
                }
                $re['content'] .= ' <a href="' . Url::log($re['id']) . '">阅读全文&gt;&gt;</a>';
            }
            $d[] = $re;
        }
        return $d;
    }

    /**
     * 获取文章所在页码
     * @param $date
     * @param $pageSize
     * @param $type
     * @return false|float
     */
    public function getPageOffset($date, $pageSize = 20, $type = 'blog') {
        $data = $this->db->once_fetch_array("SELECT COUNT(*) AS total FROM $this->table WHERE type='$type' AND hide='n' AND (date >= $date OR top = 'y' OR sortop = 'y')");
        $count = $data['total'];
        return ceil($count / $pageSize);
    }

    public function getAllPageList() {
        $sql = "SELECT * FROM $this->table WHERE type='page'";
        $res = $this->db->query($sql);
        $pages = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['date'] = date("Y-m-d H:i", $row['date']);
            $row['title'] = !empty($row['title']) ? htmlspecialchars($row['title']) : '无标题';
            $pages[] = $row;
        }
        return $pages;
    }

    /**
     * 删除商品的规格数据
     */
    public function deleteProductSpecification($goods_id){
        $this->db->query("DELETE FROM " . DB_PREFIX . "product_specification where goods_id=$goods_id");
    }

    /**
     * 写入商品的规格数据
     */
    public function insertProductSpecification($goods_id, $sku){
        $sql = "insert into ". DB_PREFIX . "product_specification (goods_id, specification, price, market_price, cost_price, stock) values ";
        foreach($sku as $val){
            $sql .= "({$val['goods_id']}, '{$val['specification']}', {$val['price']}, {$val['market_price']}, {$val['cost_price']}, {$val['stock']}),";
        }
        $sql = rtrim($sql, ',');
        $this->db->query($sql);
    }

    public function deleteProduct($goods_id) {
        $this->checkEditable($goods_id);
        $detail = $this->getDetail($goods_id);
        $author = User::haveEditPermission() ? '' : 'and author=' . UID;
        var_dump($author);
        $this->db->query("DELETE FROM $this->table where id=$goods_id $author");
        if ($this->db->affected_rows() < 1) {
            emMsg('权限不足！', './');
        }
        // comment
        $this->db->query("DELETE FROM " . DB_PREFIX . "comment where gid=$goods_id");
        // tag
        if (!empty($detail['tags'])) {
            $TagModel = new Tag_Model();
            $tags = explode(',', $detail['tags']);
            foreach ($tags as $tag) {
                $TagModel->removeBlogIdFromTag($tag, $goods_id);
            }
        }
    }

    public function hideSwitch($blogId, $state) {
        $author = User::haveEditPermission() ? '' : 'and author=' . UID;
        $this->db->query("UPDATE $this->table SET hide='$state' WHERE id=$blogId $author");
        $this->db->query("UPDATE " . DB_PREFIX . "comment SET hide='$state' WHERE gd=$blogId");
        $Comment_Model = new Comment_Model();
        $Comment_Model->updateCommentNum($blogId);
    }

    public function checkSwitch($blogId, $state) {
        $this->db->query("UPDATE $this->table SET checked='$state' WHERE id=$blogId");
        $state = $state == 'y' ? 'n' : 'y';
        $this->db->query("UPDATE " . DB_PREFIX . "comment SET hide='$state' WHERE id=$blogId");
        $Comment_Model = new Comment_Model();
        $Comment_Model->updateCommentNum($blogId);
    }

    public function unCheck($blogId, $feedback) {
        $this->db->query("UPDATE $this->table SET checked='n', feedback='$feedback' WHERE id=$blogId");
        $this->db->query("UPDATE " . DB_PREFIX . "comment SET hide='y' WHERE id=$blogId");
        $Comment_Model = new Comment_Model();
        $Comment_Model->updateCommentNum($blogId);
    }

    public function updateViewCount($blogId) {
        $this->db->query("UPDATE $this->table SET views=views+1 WHERE id=$blogId");
    }

    public function isRepeatPost($title, $time) {
        $sql = "SELECT gid FROM $this->table WHERE title='$title' and date='$time' LIMIT 1";
        $res = $this->db->query($sql);
        $row = $this->db->fetch_array($res);
        return isset($row['gid']) ? (int)$row['gid'] : false;
    }

    public function neighborLog($date) {
        $now = time();
        $date_state = "and date<=$now";
        $neighborlog = [];
        $neighborlog['nextLog'] = $this->db->once_fetch_array("SELECT title,id FROM $this->table WHERE date < $date and hide = 'n' and checked='y' and type='blog' $date_state ORDER BY date DESC LIMIT 1");
        $neighborlog['prevLog'] = $this->db->once_fetch_array("SELECT title,id FROM $this->table WHERE date > $date and hide = 'n' and checked='y' and type='blog' $date_state ORDER BY date LIMIT 1");
        if ($neighborlog['nextLog']) {
            $neighborlog['nextLog']['title'] = htmlspecialchars($neighborlog['nextLog']['title']);
        }
        if ($neighborlog['prevLog']) {
            $neighborlog['prevLog']['title'] = htmlspecialchars($neighborlog['prevLog']['title']);
        }
        return $neighborlog;
    }



    public function getHotLog($num) {
        $now = time();
        $date_state = "and date<=$now";
        $sql = "SELECT * FROM $this->table WHERE hide='n' and checked='y' and type='blog' $date_state ORDER BY views DESC, comnum DESC LIMIT 0, $num";
        $res = $this->db->query($sql);
        $logs = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['gid'] = (int)$row['gid'];
            $row['title'] = htmlspecialchars($row['title']);
            $row['cover'] = $row['cover'] ? getFileUrl($row['cover']) : '';
            $row['log_url'] = Url::log($row['gid']);
            $logs[] = $row;
        }
        return $logs;
    }

    // 检查文章别名，别名重复则重命名为 xxx-1 格式
    public function checkAlias($alias, $logalias_cache, $logid) {
        if (!preg_match('/^[a-zA-Z0-9_\-]+$/', $alias)) {
            return '';
        }
        static $i = 2;
        $key = array_search($alias, $logalias_cache);
        if (false !== $key && $key != $logid) {
            if ($i == 2) {
                $alias .= '-' . $i;
            } else {
                $alias = preg_replace("|(.*)-([\d]+)|", "$1-{$i}", $alias);
            }
            $i++;
            return $this->checkAlias($alias, $logalias_cache, $logid);
        }
        return $alias;
    }

    public function authPassword($postPwd, $cookiePwd, $logPwd, $logid) {
        $url = EM_URL;
        $pwd = $cookiePwd ?: $postPwd;
        if ($pwd !== addslashes($logPwd)) {
            if (view::isTplExist('pw')) {
                include view::getView('pw');
            } else {
                echo <<<EOT
<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name=renderer  content=webkit>
<title>请输入文章访问密码</title>
<link rel="stylesheet" type="text/css" href="{$url}admin/views/css/bootstrap.min.css">
</head>
<body class="text-center">
    <form action="" method="post" class="form-signin" style="width: 100%;max-width: 330px;padding: 15px;margin: 0 auto;">
      <input type="password" id="logpwd" name="logpwd" class="form-control" placeholder="请输入文章的访问密码" required autofocus>
      <button class="btn btn-lg btn-primary btn-block mt-2" type="submit">提交</button>
      <p class="mt-5 mb-3 text-muted"><a href="$url">&larr;返回首页</a></p>
    </form>
</body>
</html>
EOT;
            }
            if ($cookiePwd) {
                setcookie('em_logpwd_' . $logid, ' ', time() - 31536000);
            }
            exit;
        }

        setcookie('em_logpwd_' . $logid, $logPwd);
    }

    public function checkEditable($gid) {
        if (User::haveEditPermission()) {
            return;
        }
        $r = $this->getOneLogForAdmin($gid);
        if (!$r || !isset($r['checked'])) {
            return;
        }
        if ($r['checked'] === 'y' && Option::get('article_uneditable') === 'y') {
            emMsg('审核通过的文章不可编辑和删除');
        }
    }
}
