<?php

namespace app\model;

use think\Paginator;

class Article extends Base
{
    public const STATUS_NORMAL  = 1; // 正常
    public const STATUS_DISABLE = 0; // 禁用

    // 文章属性（默认）
    protected static $defaultAttributeList = [
        'top'       => '置顶',
        'hot'       => '热门',
        'recommend' => '推荐',
    ];

    public static function getAttributeList(array $categoryIds = [])
    {
        $data = [];
        $recommendCategoryList = [];
        if(count(array_intersect($categoryIds, $recommendCategoryList)) > 0) {
            $data['recommend'] = '推荐';
        }

        // 新闻动态
        $communityCategoryIds = Category::getCategoryWithChildrenIds(Category::CATEGORY_NEWS);
        if(count(array_intersect($categoryIds, $communityCategoryIds)) > 0) {
            $data['top']        = '置顶';
            $data['hot']        = '热门';
            $data['recommend']  = '推荐';
        }
        return $data;
    }

    /*********************************************
     * 分割线
     *********************************************/



    //获取最高访问的文章列表
    public static function getMostVisited($limit = 5)
    {
        if ($limit <= 0) {
            $limit = 5;
        }
        return self::order('views', 'desc')
            ->limit($limit)
            ->select()
            ->toArray();
    }

    //获取栏目下最新记录
    public static function getLatestByCategory($categoryId, $limit = 5)
    {
        if (empty($categoryId)) {
            return [];
        }
        if ($limit <= 0) {
            $limit = 5;
        }
        return self::where('category_id', $categoryId)
            ->order('id', 'desc')
            ->limit($limit)
            ->select()
            ->toArray();
    }

    //根据文章ID和栏目ID获取下一篇文章
    public static function getNextArticleBySortAndCategoryId($sort, $categoryId)
    {
        return self::alias('a')
            ->where('a.sort', '<', $sort)
            ->leftJoin('category c', 'c.id = a.category_id')
            ->where('a.category_id', $categoryId)
            ->where('a.status', 1)
            ->order('a.sort', 'desc')
            ->field('a.id,a.title,a.category_id, c.title as category_title')
            ->findOrEmpty()
            ->toArray();
    }

    //根据文章ID和栏目ID获取上一篇文章
    public static function getPrevArticleBySortAndCategoryId($sort, $categoryId)
    {
        return self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            ->where('a.sort', '>', $sort)
            ->where('a.category_id', $categoryId)
            ->where('a.status', 1)
            ->order('a.sort', 'asc')
            ->field('a.id,a.title,a.category_id, c.title as category_title')
            ->findOrEmpty()
            ->toArray();
    }

    //根据栏目ID获取文章列表
    public static function getListByCategory($categoryId, $limit = 10)
    {
        return self::where('category_id', $categoryId)
            ->where('status', 1)
            ->order("sort", 'desc')
            ->limit($limit)
            ->select()
            ->toArray();
    }

    //根据栏目ID获取文章分页列表
    public static function getListPageByCategory($categoryId, $per = 20, $keyword = '')
    {
        $where                = [
            ['category_id', '=', $categoryId],
            ['status', '=', 1],
        ];
        $param['category_id'] = $categoryId;
        if ($keyword != '') {
            $where[]          = ['title', 'like', '%'.$keyword.'%'];
            $param['keyword'] = $keyword;
        }
        $paginate = [
            'list_rows' => $per,
            'query'     => $param
        ];
        return self::where($where)
            ->order("sort", 'desc')
            ->paginate($paginate, false);
    }

    //根据栏目ID获取文章数量（状态：正常）
    public static function getNormalListCount($categoryId)
    {
        $where = [
            ['category_id', '=', $categoryId],
            ['status', '=', 1],
        ];

        return self::where($where)
            ->count();
    }

    public static function onAfterInsert($article)
    {
        $article->sort        = $article->id;
        $article->create_time = $article->update_time = time();
        $auth                 = session('auth');
        $article->created     = $article->updated = $auth['userName'];
        $article->save();
    }

    /**
     * 获取文章列表
     * @param  int  $categoryId  分类ID
     * @param  int  $per  每页数量
     * @param  string  $keyword  关键词
     * @param  array  $param  文章类型：置顶、热门、推荐 ['top','hot','recommend']
     * @param  int  $status  文章状态，-1表示不限制
     * @param  array  $orderList  排序
     * @param  bool  $onlyChild  仅获取下级 默认true false=获取所有后代分类
     * @return Paginator
     */
    public static function getList($categoryId, $per = 20, $keyword = '', $param = [], $status = -1, $orderList = ['a.sort' => 'desc'], bool $onlyChild = true)
    {
        $whereMap  = [];
        $pageParam = [];
        if (is_numeric($categoryId) && $categoryId > 0) {
            $children = Category::getChildrenByParentId($categoryId, $onlyChild);
            if (!empty($children)) {
                $categoryIds = [$categoryId];
                foreach ($children as $child) {
                    if ($child['model_id'] == Model::MODEL_ARTICLE) {
                        $categoryIds[] = $child['id'];
                    }
                }
                $whereMap[] = ['a.category_id', 'in', $categoryIds];
            } else {
                $whereMap[] = ['a.category_id', '=', $categoryId];
            }
            $pageParam['category_id'] = $categoryId;
        }
        if (!empty($keyword)) {
            $whereMap[]           = ['a.title', 'like', '%'.$keyword.'%'];
            $pageParam['keyword'] = $keyword;
        }
        if (is_array($param) && count($param) > 0) {
            $pageParam['param'] = $param;
            foreach ($param as $vo) {
                if (in_array($vo, ['top', 'hot', 'recommend'], true)) {
                    $whereMap[] = ["a.{$vo}", '=', 1];
                }
            }
        }
        $paginate = [
            'list_rows' => $per,
            'query'     => $pageParam
        ];

        return self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            ->when(count($whereMap) > 0, function ($query) use ($whereMap) {
                $query->where($whereMap);
            })
            ->when($status != -1, function ($query) use ($status) {
                $query->where('a.status', $status);
            })
            ->order($orderList)
            ->field('a.*, c.title as category_title')
            ->paginate($paginate, false);
    }

    //获取文章涉及到的图片
    public static function getFilesInUse()
    {
        $items = self::select()->toArray();
        $data  = [];
        foreach ($items as $item) {
            $src = trim($item['src']);
            if (!empty($src)) {
                $key        = getKeyByPath($src);
                $data[$key] = $src;
            }
            $imgs = getImageUrlFromText($item['content']);
            if (!empty($imgs)) {
                $data = array_merge($data, $imgs);
            }
            $videos = getVideoUrlFromText($item['content']);
            if (!empty($videos)) {
                $data = array_merge($data, $videos);
            }
        }
        return $data;
    }

    //推荐列表(其他推荐类)
    public static function getRecommendList($categoryId, $recommend = '', $limit = 3, $excludeIds = [], $orderList = ['a.id' => 'desc'])
    {
        if (empty($categoryId) || empty($recommend)) {
            return [];
        }

        $whereMap = [];
        if (is_numeric($categoryId) && $categoryId > 0) {
            $children = Category::getChildrenByParentId($categoryId);
            if (!empty($children)) {
                $categoryIds = [$categoryId];
                foreach ($children as $child) {
                    if ($child['model_id'] == Model::MODEL_ARTICLE) {
                        $categoryIds[] = $child['id'];
                    }
                }
                $whereMap[] = ['a.category_id', 'in', $categoryIds];
            } else {
                $whereMap[] = ['a.category_id', '=', $categoryId];
            }
        }
        if (!empty($excludeIds)) {
            $whereMap[] = ['a.id', 'not in', $excludeIds];
        }

        return self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            ->when(count($whereMap) > 0, function ($query) use ($whereMap) {
                $query->where($whereMap);
            })
            ->whereRaw("FIND_IN_SET(:recommend, a.`recommend_other`)", ['recommend' => $recommend])
            ->where('a.status', 1)
            ->order($orderList)
            ->limit($limit)
            ->field('a.*, c.title as category_title')
            ->select()
            ->toArray();
    }

    // 转换文章的推荐设置
    public static function convertRecommendOther($categoryIds = [], $articles, $isMulti = true)
    {
        if (empty($articles) || count($articles) == 0) {
            return $articles;
        }

        $attributeList = self::getAttributeList($categoryIds);

        if ($isMulti) {
            foreach ($articles as &$article) {
                $recommendOtherList    = [];
                $recommendOtherStrList = [];
                if (isset($article['recommend_other']) && !empty($article['recommend_other'])) {
                    $recommendOtherList = explode(',', $article['recommend_other']);
                    foreach ($recommendOtherList as $recommendKey) {
                        if (isset($attributeList[$recommendKey]) && !empty($attributeList[$recommendKey])) {
                            $recommendOtherStrList[] = $attributeList[$recommendKey];
                        }
                    }
                }
                $article['recommend_other_list'] = $recommendOtherList;
                $article['recommend_other_str']  = implode(',', $recommendOtherStrList);
            }
            unset($article);

        } else {
            $recommendOtherList    = [];
            $recommendOtherStrList = [];
            if (isset($articles['recommend_other']) && !empty($articles['recommend_other'])) {
                $recommendOtherList = explode(',', $articles['recommend_other']);
                foreach ($recommendOtherList as $recommendKey) {
                    if (isset($attributeList[$recommendKey]) && !empty($attributeList[$recommendKey])) {
                        $recommendOtherStrList[] = $attributeList[$recommendKey];
                    }
                }
            }
            $articles['recommend_other_list'] = $recommendOtherList;
            $articles['recommend_other_str']  = implode(',', $recommendOtherStrList);
        }

        return $articles;
    }

    // 获取最新动态
    public static function getLastDynamicsList($categoryId, $withChild = false, $limit = 10)
    {
        $categoryIds = [$categoryId];
        if ($withChild) {
            $childCategories = Category::getChildrenByParentId($categoryId);
            if (!empty($childCategories)) {
                foreach ($childCategories as $category) {
                    if ($category['model_id'] == Model::MODEL_ARTICLE) {
                        $categoryIds[] = $category['id'];
                    }
                }
            }
        }

        return self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            ->whereIn('a.category_id', $categoryIds)
            ->where('a.status', 1)
            ->order('a.id', 'desc')
            ->limit($limit)
            ->field('a.*, c.title as category_title')
            ->select()
            ->toArray();

    }


    //根据文章ID和栏目IDs，默认按创建时间获取下一篇文章
    public static function getNextArticleByTimeAndCategoryIds(array $where, $sortOrder = ['a.id' => 'desc'])
    {
        return self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            ->where($where)
            ->where('a.status', 1)
            ->order($sortOrder)
            ->field('a.*, c.title as category_title')
            ->findOrEmpty()
            ->toArray();
    }

    //根据文章ID和栏目IDs，默认按创建时间获取上一篇文章
    public static function getPrevArticleByTimeAndCategoryIds(array $where, $sortOrder = ['a.id' => 'asc'])
    {
        return self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            //        ->where('a.id','>',$curId)
            //        ->whereIn('a.category_id', $categoryIds)
            ->where($where)
            ->where('a.status', 1)
            ->order($sortOrder)
            ->field('a.*, c.title as category_title')
            ->findOrEmpty()
            ->toArray();
    }

    public static function getLastTopList($categoryId, $limit = 3, $excludeIds = [], $orderList = ['a.recommend_other' => 'desc', 'a.id' => 'desc'])
    {
        if (empty($categoryId)) {
            return [];
        }

        $whereMap = [];
        if (is_numeric($categoryId) && $categoryId > 0) {
            $children = Category::getChildrenByParentId($categoryId);
            if (!empty($children)) {
                $categoryIds = [$categoryId];
                foreach ($children as $child) {
                    if ($child['model_id'] == Model::MODEL_ARTICLE) {
                        $categoryIds[] = $child['id'];
                    }
                }
                $whereMap[] = ['a.category_id', 'in', $categoryIds];
            } else {
                $whereMap[] = ['a.category_id', '=', $categoryId];
            }
        }
        if (!empty($excludeIds)) {
            $whereMap[] = ['a.id', 'not in', $excludeIds];
        }

        $items = self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            ->when(count($whereMap) > 0, function ($query) use ($whereMap) {
                $query->where($whereMap);
            })
            ->where('a.status', 1)
            ->order($orderList);
        if ($limit > 0) {
            $items = $items->limit($limit);
        }
        $items = $items->limit($limit)
            ->field('a.*, c.title as category_title')
            ->select()
            ->toArray();

        return $items;
    }

    // 分页获取最新动态
    public static function getLastDynamicsPageList($categoryId, $withChild = true, $per = 20)
    {
        $categoryIds = [$categoryId];
        if ($withChild) {
            $childCategories = Category::getChildrenByParentId($categoryId);
            if (!empty($childCategories)) {
                foreach ($childCategories as $category) {
                    if ($category['model_id'] == Model::MODEL_ARTICLE) {
                        $categoryIds[] = $category['id'];
                    }
                }
            }
        }

        $paginate = [
            'list_rows' => $per,
            'query'     => [
                'category_id' => $categoryId
            ]
        ];

        return self::alias('a')
            ->leftJoin('category c', 'c.id = a.category_id')
            ->whereIn('a.category_id', $categoryIds)
            ->where('a.status', 1)
            ->order('a.id', 'desc')
            ->field('a.*, c.title as category_title')
            ->paginate($paginate, false);
    }

    // 根据栏目ID进行分组，按sort倒序排列，每组最多获取n条(默认10条)数据
    public static function getGroupListByCategoryIds(array $categoryIds, int $size = 10)
    {
        return self::alias('ca')
            ->where($size, '>', function ($q) {
                $q->table('bee_article cb')
                    ->whereRaw('ca.category_id = cb.category_id and ca.sort < cb.sort')->field('count(*)');
            })
            ->whereIn('ca.category_id', $categoryIds)
            ->field('ca.*')
            ->order(['ca.sort' => 'desc'])
            ->select();
    }

    public static function parseList($items)
    {
        try {
            $tagNameList = [];
            foreach ($items as $ki => $item) {
                $tagStr      = trim($item['tag'] ?? '');
                $tagNames    = empty($tagStr) ? [] : explode(',', $tagStr);
                $tagNameList = array_merge($tagNameList, $tagNames);
            }
            $tagNameList = array_unique($tagNameList);
            $tagKVs      = ArticleTags::findByNames($tagNameList)->column('id', 'name');

            foreach ($items as $ki => $item) {
                $tagStr   = trim($item['tag'] ?? '');
                $tagNames = empty($tagStr) ? [] : explode(',', $tagStr);
                $tagList  = [];
                foreach ($tagNames as $tagName) {
                    $tagList[] = [
                        'name' => $tagName,
                        'id'   => $tagKVs[$tagName] ?? 0
                    ];
                }
                $items[$ki]['tag_list']    = $tagList;
                $createTime                = is_numeric($item['create_time']) ? $item['create_time'] : strtotime($item['create_time']);
                $items[$ki]['create_date'] = date('Y-m-d', $createTime);
                $item['create_dateTime']   = date('Y-m-d H:i:s', $createTime);
            }
        } catch (\Exception $e) {

        }
        return $items;
    }

    public static function parseInfo($item)
    {
        if ($item) {
            $tagStr      = trim($item['tag'] ?? '');
            $tagNameList = empty($tagStr) ? [] : explode(',', $tagStr);
            $tagKVs      = ArticleTags::findByNames($tagNameList)->column('id', 'name');
            $tagList     = [];
            foreach ($tagNameList as $tagName) {
                $tagList[] = [
                    'name' => $tagName,
                    'id'   => $tagKVs[$tagName] ?? 0
                ];
            }
            $item['tag_list']        = $tagList;
            $createTime              = is_numeric($item['create_time']) ? $item['create_time'] : strtotime($item['create_time']);
            $item['create_date']     = date('Y-m-d', $createTime);
            $item['create_dateTime'] = date('Y-m-d H:i:s', $createTime);
        }
        return $item;
    }

    public static function countList(array $where, callable $call = null)
    {
        $q = new static();
        $q = $q->where($where);
        if ($call) {
            $q = $call($q);
        }
        return $q->count();
    }

    public static function findListByWhere(array $where, int $page = 1, int $size = 10, callable $call = null, array $sortList = [])
    {
        $q = new static();
        $q = $q->where($where);
        if ($call) {
            $q = $call($q);
        }
        if ($size > 0) {
            $q = $q->page($page, $size);
        }
        if (count($sortList)) {
            $q = $q->order($sortList);
        }
        return $q->select();
    }
}