<?php

namespace App\Modules\Book\Services;

use App\Consts\SysConsts;
use App\Modules\Book\Models\Book;
use App\Modules\Book\Models\BookConfig;
use App\Modules\Book\Models\CrmBookAutoRecommend;
use DB;
use Redis;

use function GuzzleHttp\json_decode;

class CrmBookAutoRecommendService
{
   private $this_week;

   private $redis_key;

   public function __construct()
   {
      $this->this_week = date('Ymd', strtotime('this week Monday'));
      $this->redis_key =  'crm_book_auto_recommend:' . $this->this_week;
   }

   /**
    * 生成推荐书籍
    */
   public function generateRecommendBooks()
   {
      if (CrmBookAutoRecommend::where('week', $this->this_week)->exists()) {
         return;
      } else {
         $categories = BookConfig::join('books', 'books.id', 'book_configs.bid')
            ->select('books.category_id')
            ->where('book_configs.is_on_shelf', 2)->where('book_configs.recommend_index', '>=', 80)
            ->groupBy('books.category_id')
            ->havingRaw('count(1)>=10')
            ->get();
         $categories =  $categories->shuffle()->take(3)->all();
         if ($categories) {
            collect($categories)->each(function ($item) {
               $books = BookConfig::join('books', 'books.id', 'book_configs.bid')
                  ->where('books.category_id', $item->category_id)
                  ->where('book_configs.is_on_shelf', 2)->where('book_configs.recommend_index', '>=', 80)
                  ->select('book_configs.bid')
                  ->get();
               $books = $books->shuffle()->take(10)->all();
               $recommends = BookConfig::join('books', 'books.id', 'book_configs.bid')
                  ->join('book_categories', 'book_categories.id', 'books.category_id')
                  ->whereIn('book_configs.bid', collect($books)->pluck('bid')->all())
                  ->select('book_configs.bid', 'book_configs.book_name', 'books.category_id', 'book_categories.category_name')
                  ->get();
               $recommends = $recommends->transform(function ($item) {
                  return [
                     'week' => $this->this_week,
                     'bid' => $item->bid,
                     'name' => $item->book_name,
                     'category_id' => $item->category_id,
                     'category_name' => $item->category_name,
                  ];
               });
               DB::table('crm_book_auto_recommend')->insert($recommends->all());
            });
         }
      }
   }

   /**
    * 设置redis缓存
    */
   public function setRecommendBooksRedis()
   {
      $results = $this->getRecommendBooksFromDB();
      if ($results) {
         Redis::setex($this->redis_key, SysConsts::ONE_WEEK_SECONDS, json_encode($results));
      }
      return $results;
   }

   /**
    * 获取推荐书籍
    */
   public function getRecommendBooksFromRedis()
   {
      $value = Redis::get($this->redis_key);
      if ($value) {
         return json_decode($value, true);
      } else {
         return  $this->setRecommendBooksRedis();
      }
   }

   /**
    * 获取推荐书籍
    */
   private function getRecommendBooksFromDB()
   {
      $recommends = CrmBookAutoRecommend::where('week', $this->this_week)->get();
      $bids = $recommends->pluck('bid')->all();
      $configs = BookConfig::whereIn('bid', $bids)->select('bid', 'cover', 'recommend_index')->get();
      $books = Book::whereIn('id', $bids)->select('id', 'status', 'intro', 'size', 'last_cid', 'last_chapter')->get();
      $results = $recommends->map(function ($item) use ($books, $configs) {
         $bid = $item->bid;
         $name = $item->name;
         $category_id = $item->category_id;
         $category_name = $item->category_name;
         $config = $configs->where('bid', $bid)->first();
         $book =  $books->where('id', $bid)->first();
         $cover = $config->cover;
         $recommend_index = $config->recommend_index;
         $intro = $book->intro;
         $status = $book->status;
         $size = $book->size;
         $last_cid = $book->last_cid;
         $last_chapter = $book->last_chapter;
         $is_vip = 1;
         return compact('bid', 'name', 'category_id', 'category_name', 'cover', 'recommend_index', 'status', 'intro', 'size', 'last_cid', 'last_chapter', 'is_vip');
      })->all();
      return $results;
   }
}
