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

class Goods_Model {

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

    public function __construct() {
        $this->db = Database::getInstance();
        $this->table = DB_PREFIX . 'goods';
        $this->table_user = DB_PREFIX . 'user';
        $this->table_sort = DB_PREFIX . 'sort';
        $this->Parsedown = new Parsedown();
        $this->Parsedown->setBreaksEnabled(true); //automatic line wrapping
    }

    /**
     * create product
     */
    public function addProduct($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();
    }

    /**
     * update article
     */
    public function updateProduct($logData, $goods_id, $uid = UID) {
        $Item = [];
        foreach ($logData as $key => $data) {
            $Item[] = "$key='$data'";
        }
        $upStr = implode(',', $Item);
        $sql = "UPDATE $this->table SET $upStr WHERE id=$goods_id";
//        echo $sql;die;
        $this->db->query($sql);
    }

    public function getCount() {
        $sql = "SELECT count(*) as num FROM $this->table WHERE type='goods' and delete_time is null";
        $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 getGoodsNum() {

        $data = $this->db->once_fetch_array("SELECT COUNT(*) AS total FROM $this->table where delete_time is null");
        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 getOneGoodsForAdmin($goods_id) {

        $sql = "select * from {$this->table} where id={$goods_id} limit 1";
        $goods = $this->db->once_fetch_array($sql);
        $sql = "select * from " . DB_PREFIX . "skus where goods_id={$goods_id}";
        $skus = $this->db->fetch_all($sql);
        foreach($skus as $key => $val){
            $sql = "select * from " . DB_PREFIX . "member_price where goods_id={$goods_id} and sku='" . $val['sku'] . "'";
            $member_prices = $this->db->fetch_all($sql);
            $skus[$key]['member_prices'] = $member_prices;
        }
        $goods['skus'] = $skus;
        $goods['post_url'] = $val['post_url'];

        if ($goods) {

            $goods['skus_json'] = json_encode($goods['skus']);

            $goods['title'] = htmlspecialchars($goods['title']);
            $goods['content'] = htmlspecialchars($goods['content']);
            $goods['password'] = htmlspecialchars($goods['password']);
            $goods['template'] = !empty($goods['template']) ? htmlspecialchars(trim($goods['template'])) : 'page';
            return $goods;
        }
        return false;
    }

    public function getGoodsSkusForAdmin($goods_id){

        $sql = "SELECT * FROM $this->table WHERE id=$goods_id";
        $res = $this->db->query($sql);
        $goods = $this->db->fetch_array($res);


        $sql = "SELECT * FROM `" . DB_PREFIX . "skus` where goods_id={$goods_id}";
        $result = $this->db->query($sql);
        $data = [];



        while ($row = $this->db->fetch_array($result)) {
            if($goods['is_sku'] == 'y'){
                $data["skus[{$row['sku']}][guest_price]"] = $row['guest_price'] / 100;
                $data["skus[{$row['sku']}][user_price]"] = $row['user_price'] / 100;
                $data["skus[{$row['sku']}][market_price]"] = $row['market_price'] / 100;
                $data["skus[{$row['sku']}][cost_price]"] = $row['cost_price'] / 100;

                $sql = "SELECT * FROM `" . DB_PREFIX . "member_price` where goods_id={$row['goods_id']}";
                $res = $this->db->query($sql);
                while ($r = $this->db->fetch_array($res)) {
                    if($row['sku'] == $r['sku']){
                        $data["skus[{$row['sku']}][member_{$r['member_level']}]"] = $r['price'] / 100;
                    }

                }

            }else{
                $data['guest_price'] = $row['guest_price'] / 100;
                $data['user_price'] = $row['user_price'] / 100;
                $data['market_price'] = $row['market_price'] / 100;
                $data['cost_price'] = $row['cost_price'] / 100;
            }
        }

//        d($data);die;


        return $data;
    }

    public function getDetail($goods_id) {
        if (empty($goods_id)) {
            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=$goods_id";
        $res = $this->db->query($sql);
        $row = $this->db->fetch_array($res);
        if ($row) {
            return $row;
        }
        return false;
    }

    public function getDetails($goods_ids) {
        if (empty($goods_ids) || !is_array($goods_ids)) {
            return false;
        }
        $goods_idsString = implode(',', $goods_ids);
        $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 ($goods_idsString)";
        $res = $this->db->query($sql);
        $rows = array();
        while ($row = $this->db->fetch_array($res)) {
            $rows[] = $row;
        }
        return $rows;
    }

    /**
     * get single article
     * @param $goods_id
     * @return array|false
     */
    public function getOneGoodsForHome($goods_id) {
        $db_prefix = DB_PREFIX;

        $sql = "select * from {$db_prefix}goods where id={$goods_id} limit 1";
        $goods = $this->db->once_fetch_array($sql);

        if($goods['is_on_shelf'] == 0){
            emMsg('该商品已下架！');
        }

        $sql = "select * from {$db_prefix}skus where goods_id={$goods_id}";
        $skus = $this->db->fetch_all($sql);
        $sql ="select * from {$db_prefix}member_price where goods_id={$goods_id}";
        $member_price = $this->db->fetch_all($sql);
        $sql = "select goods_id, sku, sum(quantity) stock from {$db_prefix}stock where goods_id={$goods_id} group by sku";
        $stock = $this->db->fetch_all($sql);

        $goods['attach_user'] = json_decode($goods['attach_user'], true);

        if($goods['is_sku'] == 'y'){
            $sku_value_ids = [];
            $sku_attr_ids = [];
            $goods['have_stock_skus'] = [];
            $goods['stock'] = 0;
            $goods['sku_all'] = [];
            foreach($skus as $key => $val){

                $ids = explode('-', $val['sku']);
                $sku_value_ids = array_merge($sku_value_ids, $ids);

                $price = -1;
                if(LEVEL == -1){
                    $price= $val['guest_price'] / 100;
                }else{
                    foreach($member_price as $v){
                        if($v['member_level'] == LEVEL && $val['sku'] == $v['sku']){
                            $price = $v['price'] / 100;
                        }
                    }
                    $price = $price == -1 ? $val['user_price'] / 100 : $price;
                }
                $val['price'] = $price;

                $goods['sku_all'][$val['sku']] = $val;
                $goods['sku_all'][$val['sku']]['stock'] = 0;
                foreach($stock as $v){
                    $skus[$key]['stock'] = 0;

                    if($v['sku'] == $val['sku']){
                        $goods['sku_all'][$val['sku']]['stock'] = $v['stock'];
                        $skus[$key]['stock'] = $v['stock'];
                        if($v['stock'] > 0){
                            $goods['stock'] += $v['stock'];
                            $goods['have_stock_skus'][$val['sku']] = array_merge($val, ['stock' => $v['stock']]);
                        }
                    }

                }

            }
            $sku_value_ids = array_unique($sku_value_ids);
            $sql = "SELECT * FROM {$db_prefix}sku_value WHERE id IN (" . implode(',', $sku_value_ids) . ")";
            $sku_values = $this->db->fetch_all($sql);
            foreach($sku_values as $val){
                $sku_attr_ids[] = $val['attr_id'];
            }
            $sku_attr_ids = array_unique($sku_attr_ids);
            $sql = "SELECT * FROM {$db_prefix}sku_attr WHERE id IN (" . implode(',', $sku_attr_ids) . ")";
            $sku_attr = $this->db->fetch_all($sql);

            $goods['spec'] = [];
            $goods['spec_attr'] = [];
            foreach($sku_attr as $key => $val){
                $goods['spec'][$key] = [
                    'sku_attr_id' => $val['id'],
                    'title' => $val['title'],
                    'sku_values' => []
                ];


                foreach($sku_values as $v){
                    if($val['id'] == $v['attr_id']){
                        $goods['spec'][$key]['sku_values'][] = [
                            'id' => $v['id'],
                            'name' => $v['name']
                        ];
                        $goods['spec_attr'][$key][] = $v['id'];
                    }

                }


            }

            $goods['skus_all_json'] = json_encode($goods['sku_all']);
            $goods['spec_attr_json'] = json_encode($goods['spec_attr']);
            $goods['have_stock_skus_json'] = json_encode($goods['have_stock_skus']);
        }else{
            $goods['stock'] = 0;
            foreach($skus as $key => $val){
                $price = -1;
                if(LEVEL == -1){
                    $price= $val['guest_price'] / 100;
                }else{
                    foreach($member_price as $v){
                        if($v['member_level'] == LEVEL && $val['sku'] == $v['sku']){
                            $price = $v['price'] / 100;
                        }
                    }
                    $price = $price == -1 ? $val['user_price'] / 100 : $price;
                }

                foreach($stock as $v){
                    $goods['stock'] += $v['stock'];
                }

            }
            $goods['spec_attr_json'] = json_encode([]);

            $goods['have_stock_skus'][] = array_merge($val, ['price' => $price, 'stock' => $goods['stock']]);

            $goods['have_stock_skus_json'] = json_encode($goods['have_stock_skus']);
            $goods['skus_all_json'] = json_encode([]);
        }

        $goods['content'] = $this->Parsedown->text($goods['content']);


        return $goods;
    }

    public function getGoodsForAdmin($order = '', $page = 1) {
        $perpage_num = Option::get('admin_article_perpage_num');
        $start_limit = !empty($page) ? ($page - 1) * $perpage_num : 0;
        $limit = "LIMIT $start_limit, " . $perpage_num;


        $sql = "
SELECT 
    g.*, COALESCE(SUM(s.quantity), 0) AS stock
FROM 
    {$this->table} g
LEFT JOIN 
    " . DB_PREFIX . "skus sk ON g.id = sk.goods_id
LEFT JOIN 
    " . DB_PREFIX . "stock s ON sk.goods_id = s.goods_id AND sk.sku = s.sku
where g.delete_time is null
GROUP BY 
    g.id
ORDER BY id desc
$limit;
";

        $res = $this->db->query($sql);
        $logs = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['timestamp'] = $row['create_time'];
            $row['create_time'] = date("Y-m-d H:i", $row['create_time']);
            $row['title'] = !empty($row['title']) ? htmlspecialchars($row['title']) : '无标题';
            $logs[] = $row;
        }
        return $logs;
    }

    public function getGoodsForHome($condition = '', $page = 1, $perPageNum = 10, $order_by) {
        $start_limit = !empty($page) ? ($page - 1) * $perPageNum : 0;

        $condition = empty($condition) ? "where g.delete_time is null" : " where " . $condition . " and g.delete_time is null";

        $limit = $perPageNum ? "LIMIT $start_limit, $perPageNum" : '';
        $sql = "
SELECT 
    g.*, 
    COALESCE(SUM(s.quantity), 0) AS stock,
    sk_min.guest_price,
    sk_min.cost_price,
    sk_min.user_price,
    sk_min.market_price,
    mp_min.price AS member_price
FROM 
    {$this->table} g
LEFT JOIN (
    SELECT 
        goods_id, 
        MIN(guest_price) AS guest_price,
        MIN(cost_price) AS cost_price,
        MIN(user_price) AS user_price,
        MIN(market_price) AS market_price
    FROM 
        " . DB_PREFIX . "skus
    GROUP BY 
        goods_id
) sk_min ON g.id = sk_min.goods_id
LEFT JOIN (
    SELECT 
        goods_id, 
        MIN(price) AS price
    FROM 
        " . DB_PREFIX . "member_price
    WHERE 
        member_level = " . LEVEL . "
    GROUP BY 
        goods_id
) mp_min ON g.id = mp_min.goods_id
LEFT JOIN 
    " . DB_PREFIX . "stock s ON g.id = s.goods_id AND sk_min.guest_price = (
        SELECT guest_price 
        FROM " . DB_PREFIX . "skus 
        WHERE goods_id = g.id 
        ORDER BY guest_price ASC 
        LIMIT 1
    )
$condition AND g.is_on_shelf = 1
GROUP BY 
    g.id
ORDER BY 
    {$order_by}
$limit;
";
//echo $sql;die;
        $res = $this->db->query($sql);
        $goods = [];


        while ($row = $this->db->fetch_array($res)) {
            $row['url'] = Url::goods($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['market_price'] /= 100;
            $row['cost_price'] /= 100;
            $row['guest_price'] /= 100;
            $row['user_price'] /= 100;

            if(LEVEL == -1){
                $row['price'] = $row['guest_price'];
            }else{
                if(empty($row['member_price'])){
                    $row['price'] = $row['user_price'];
                }else{
                    $row['price'] = $row['member_price'] / 100;
                }
            }





            $goods[] = $row;
        }
//        d($goods);die;
        return $goods;
    }

    /**
     * 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')");
        $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 deleteProductSku($goods_id){
        $this->db->query("DELETE FROM " . DB_PREFIX . "skus where goods_id=$goods_id");
        $this->db->query("DELETE FROM " . DB_PREFIX . "member_price where goods_id=$goods_id");
    }

    /**
     * 写入商品的规格数据
     */
    public function insertProductSkus($goods_id, $sku){
        // 构建SQL语句
        $sql = "INSERT INTO " . DB_PREFIX . "skus 
            (goods_id, sku, guest_price, user_price, market_price, cost_price, post_url) 
            VALUES 
            ({$goods_id}, '{$sku['sku']}', {$sku['guest_price']}, {$sku['user_price']}, {$sku['market_price']}, {$sku['cost_price']}, '{$sku['post_url']}')";

//        echo $sql;die;

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

    public function delMemberPrice($goods_id){
        $this->db->query("DELETE FROM " . DB_PREFIX . "member_price where goods_id=$goods_id");
    }

    public function insertMemberPrice($data) {


        $sql = "INSERT INTO " . DB_PREFIX . "member_price (goods_id, sku, member_level, price) VALUES ({$data['goods_id']}, '{$data['sku']}', {$data['member_level']}, {$data['price']})";
        $this->db->query($sql);
    }

    public function deleteProduct($goods_id) {
        $timestamp = time();
        $this->db->query("UPDATE $this->table set delete_time={$timestamp} where id=$goods_id");
        if ($this->db->affected_rows() < 1) {
            emMsg('权限不足！', './');
        }
    }

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

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

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

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

    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 getRandLog($num) {
        global $CACHE;
        $now = time();
        $date_state = "and date<=$now";
        $sta_cache = $CACHE->readCache('sta');
        $lognum = $sta_cache['lognum'];
        $start = $lognum > $num ? mt_rand(0, $lognum - $num) : 0;
        $sql = "SELECT gid,title FROM $this->table WHERE hide='n' and checked='y' and type='blog' $date_state LIMIT $start, $num";
        $res = $this->db->query($sql);
        $logs = [];
        while ($row = $this->db->fetch_array($res)) {
            $row['gid'] = (int)$row['gid'];
            $row['title'] = htmlspecialchars($row['title']);
            $logs[] = $row;
        }
        return $logs;
    }

    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('审核通过的文章不可编辑和删除');
        }
    }
}
