<?php

namespace App\Http\Controllers;

use App\Area;
use App\Consultation;
use App\ConsultationDetail;
use App\Fortunemethod;
use App\FortunemethodDetail;
use App\Http\Resources\FortunetellerResource;
use App\Http\Resources\FortunetellerShopResource;
use App\Fortuneteller;
use App\RefName;
use App\Shop;
use App\Keyword;
use App\KeywordDetail;
use Illuminate\Support\Facades\Cache;
use Carbon\Carbon;
use DB;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;

class FortunetellerController extends Controller
{
    const ITEM_PER_PAGE = 28;

    public function index(Request $request)
    {
        $params = $request->all();
        $list = Fortuneteller::select('id', 'number', 'slug', 'name', 'gender', 'cost', 'display_name', 'avatar', 'message', 'desc_1_full', 'shop_id', 'created_at')
            ->where('is_activated', true)
            ->where('is_deleted', false);
        $limit = Arr::get($params, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($params, 'keyword', '');
        $method = Arr::get($params, 'method', '');
        $consultation = Arr::get($params, 'consultation', '');
        $refName = Arr::get($params, 'refName', '');
        $address = Arr::get($params, 'address', '');
        $gender = Arr::get($params, 'gender', '');
        $area = Arr::get($params, 'area', '');
        $checkFeMale = isset($params['checkFeMale']) ? $params['checkFeMale'] : 'false';
        $checkMale = isset($params['checkMale']) ? $params['checkMale'] : 'false';
        $checkMethod = isset($params['checkMethod']) ? $params['checkMethod'] : 'false';
        $orderBy = Arr::get($params, 'sorting', 'date');
        $listFilterIds = [];
        $checkFilterId = false;

        if (!empty($keyword)) {
            $checkFilterKeyword = [];
            $kItem = Keyword::where('is_activated', true)->where('is_deleted', false)->where('name', $keyword)->first();
            if (isset($kItem)) {
                $kDetail = KeywordDetail::select('id', 'ref_id', 'keyword_id')->where('type', 'teller')->where('keyword_id', $kItem->id)->get();
                foreach ($kDetail as $v) {
                    $checkFilterKeyword[] = $v->ref_id;
                }
            }

            $shopListIds = Shop::select('id')
                ->where('is_activated', true)
                ->where('is_deleted', false)
                ->where(function ($query) use ($keyword, $checkFilterKeyword) {
                    $query->where('name', 'like', "%$keyword%")
                        ->orWhere('slug', 'like', "%$keyword%")
                        ->orWhere('description', 'like', "%$keyword%")
                        ->orWhereIn('id', $checkFilterKeyword);
                })
                ->pluck('id')
                ->toArray();

            $methodKeywordList = Fortunemethod::select('id')->where('is_deleted', false)->where('is_activated', true)->where('name', $keyword)->pluck('id')->toArray();
            $methodDetailIds = FortunemethodDetail::select('fortune_teller_id')->whereIn('fortune_method_id', $methodKeywordList)->pluck('fortune_teller_id')->toArray();
            if (count($methodDetailIds) > 0) {
                foreach ($methodDetailIds as $m) {
                    if (!in_array($m, $checkFilterKeyword)) $checkFilterKeyword[] = $m;
                }
            }

            $consultationKeywordList = Consultation::select('id')->where('is_deleted', false)->where('is_activated', true)->where('name', $keyword)->pluck('id')->toArray();
            $consultationDetailIds = ConsultationDetail::select('fortune_teller_id')->whereIn('consultation_id', $consultationKeywordList)->pluck('fortune_teller_id')->toArray();
            if (count($consultationDetailIds) > 0) {
                foreach ($consultationDetailIds as $c) {
                    if (!in_array($c, $checkFilterKeyword)) $checkFilterKeyword[] = $c;
                }
            }

            $list->where(function ($query) use ($keyword, $shopListIds, $checkFilterKeyword) {
                $query->where('name', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('number', '=', $keyword)
                    ->orWhere('display_name', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('address', 'LIKE', '%' . $keyword . '%')
                    ->orWhereIn('shop_id', $shopListIds)
                    ->orWhereIn('id', $checkFilterKeyword);
            });
        }

        if (!empty($method)) {
            $cMethod = Fortunemethod::where('is_deleted', 0)->where('is_activated', 1)->where('slug', $method)->first();
            if (isset($cMethod)) {
                $mIds = FortunemethodDetail::select('fortune_teller_id')->where('fortune_method_id', $cMethod->id)->get();
                foreach ($mIds as $v) {
                    if (!in_array($v->fortune_teller_id, $listFilterIds)) {
                        $listFilterIds[] = $v->fortune_teller_id;
                    }
                }
                $checkFilterId = true;
            }
        }

        if (!empty($consultation)) {
            $cIds = ConsultationDetail::select('fortune_teller_id')->where('consultation_id', $consultation)->get();
            foreach ($cIds as $v) {
                if (!in_array($v->fortune_teller_id, $listFilterIds)) {
                    $listFilterIds[] = $v->fortune_teller_id;
                }
            }
            $checkFilterId = true;
        }

        if ($checkFilterId) {
            $list->whereIn('id', $listFilterIds);
        }

        if ($checkFeMale == 'true' && $checkMale == 'true') {
            $list->where(function ($query) {
                $query->where('gender', 0)->orWhere('gender', 1);
            });
        } else {
            if ($checkFeMale == 'true') {
                $list->where('gender', 0);
            }
            if ($checkMale == 'true') {
                $list->where('gender', 1);
            }
        }

        if ($checkMethod == 'true') {
            $methodChecking = Fortunemethod::where('is_deleted', 0)->where('is_activated', 1)->where('name', '霊感')->first();
            if (isset($methodChecking)) {
                $methodCheckList = FortunemethodDetail::select('fortune_teller_id')->where('fortune_method_id', $methodChecking->id)->pluck('fortune_teller_id')->toArray();
                $list->whereIn('id', $methodCheckList);
            }
        }

        if (!empty($refName)) {
            $list->where('ref_name_id', $refName);
        }

        if (!empty($address)) {
            $list->where('address', $address);
        }

        if ($gender != '') {
            if ($gender != 1 && $gender != 0 && $gender != "1" && $gender != "0") $gender = 2;
            $list->where('gender', $gender);
        }

        if ($area != null && $area != "") {
            $shopListId = [];
            $areaAll = Area::select('id', 'slug', 'parent_id')->where('is_deleted', 0)->where('is_activated', 1)->get();
            $cArea = "";
            foreach ($areaAll as $item) {
                if ($item->slug == $area) {
                    $cArea = $item->id;
                    break;
                }
            }
            $listAreaId = [$cArea];
            if ($cArea != "") {
                $areaId = $this->getAreaItem($areaAll, $cArea);
                foreach ($areaId as $it) $listAreaId[] = $it;
            }
            if (count($listAreaId) > 0) {
                $shopListId = Shop::select('id')->where('is_deleted', 0)->where('is_activated', 1)->whereIn('area_id', $listAreaId)->pluck('id');
            }
            $list->whereIn('shop_id', $shopListId);
        }

        if ($orderBy == 'name') {
            $list->orderBy('name')->orderBy('display_name');
        } else {
            $list->orderBy('created_at', 'DESC');
        }

        return FortunetellerResource::collection($list->paginate($limit));
    }

    private function getAreaItem($list, $parentId)
    {
        $areaList = [];
        if ($parentId != null && $parentId != "") {
            foreach ($list as $item) {
                if ($item->parent_id == $parentId) {
                    $areaList[] = $item->id;
                    $child = $this->getAreaItem($list, $item->id);
                    foreach ($child as $c) $areaList[] = $c;
                }
            }
        }

        return $areaList;
    }

    public function show($code = '', Request $request)
    {
        $fortuneteller = Fortuneteller::select('*')
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->where(function ($query) use ($code) {
                $query->where('id', $code)
                    ->orWhere('slug', $code)
                    ->orWhere('number', $code);
            })
            ->first();

        if (!isset($fortuneteller) && $request->has('preview') && $request->get('preview') !== "" && $request->get('preview') !== "null") {
            $fortuneteller = Fortuneteller::select('*')
                ->where('preview_code', $request->get('preview'))
                ->where('is_deleted', false)
                ->where(function ($query) use ($code) {
                    $query->where('id', $code)
                        ->orWhere('slug', $code)
                        ->orWhere('number', $code);
                })
                ->first();
        }
        if (!isset($fortuneteller)) return response()->json(['data' => ['status' => 'error', 'message' => 'Fortuneteller is not found']], 200);

        return new FortunetellerShopResource($fortuneteller);
    }

    public function showRelate($code = '', Request $request)
    {
        $fortuneteller = Fortuneteller::select('*')
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->where(function ($query) use ($code) {
                $query->where('id', $code)
                    ->orWhere('slug', $code)
                    ->orWhere('number', $code);
            })
            ->first();

        if (!isset($fortuneteller) && $request->has('preview') && $request->get('preview') !== "" && $request->get('preview') !== "null") {
            $fortuneteller = Fortuneteller::select('*')
                ->where('preview_code', $request->get('preview'))
                ->where('is_deleted', false)
                ->where(function ($query) use ($code) {
                    $query->where('id', $code)
                        ->orWhere('slug', $code)
                        ->orWhere('number', $code);
                })
                ->first();
        }
        if (!isset($fortuneteller)) return response()->json(['data' => null], 200);

        $params = $request->all();
        $limit = Arr::get($params, 'limit', 10);
        $shop = Shop::where('id', $fortuneteller->shop_id)->first();
        $areaShopIds = Shop::select('id')->where('area_id', $shop->area_id)->pluck('id')->toArray();

        $list = Fortuneteller::select('id', 'number', 'slug', 'name', 'display_name', 'desc_1_full', 'avatar')
            ->where('is_deleted', false)
            ->where('is_activated', true)
            ->where('id' , '!=', $fortuneteller->id)
            ->whereIn('shop_id', $areaShopIds)
            ->orderBy('updated_at', 'DESC')
            ->paginate($limit);

        return response()->json($list, 200);
    }

    public function address()
    {
        $addresses = Fortuneteller::select('address', DB::raw('count(*) as total'))->isPublished()
            ->whereNotNull('address')
            ->groupBy('address')
            ->get();

        return response()->json(['data' => $addresses], 200);
    }

    public function filterName()
    {
        $refName = RefName::select('id', 'name')->get();
        return response()->json(['data' => $refName], 200);
    }

    public function filterNameById($id = 0)
    {
        $refName = RefName::select('id', 'name')->where('id', $id)->first();
        if (!isset($refName)) return response()->json(['data' => ['status' => 'error', 'message' => 'Name word is not found']], 200);

        return response()->json(['data' => $refName], 200);
    }

    public function top()
    {
        $list = Fortuneteller::select('id', 'name', 'slug', 'display_name', 'message', 'avatar')
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->where('show_top', true)
            ->orderBy('id', 'DESC')
            ->limit(30)
            ->get();

        return response()->json(['data' => $list], 200);
    }

    public function latest(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', 10);

        $list = Cache::remember('fortune_latest_' . $limit, (7*24*60*60), function () use ($limit) {
            $items = Fortuneteller::with('seo_desc')->select('id', 'number', 'slug', 'name', 'display_name', 'desc_1_full', 'avatar')
                ->where('is_deleted', false)
                ->where('is_activated', true)
                ->orderBy('created_at', 'DESC')
                ->paginate($limit);

            return ['items' => $items, 'lastModify' => (gmdate('D, d M Y H:i:s') . ' GMT')];
        });

        return response()->json($list['items'], 200)->header('Last-Modified', $list['lastModify']);
    }

    public function latestPopular(Request $request)
    {
        $params = $request->all();
        $limit = Arr::get($params, 'limit', 30);
        $list = Fortuneteller::select('id', 'number', 'slug', 'name', 'display_name', 'desc_1_full', 'avatar')
                ->where('is_deleted', false)
                ->where('is_activated', true)
                ->where('is_popular', true)
                ->orderBy('updated_at', 'DESC')
                ->paginate($limit);

        return response()->json($list, 200);
    }

    public function searching(Request $request)
    {
        $keyword = '';
        if ($request->has('keyword')) $keyword = $request->get('keyword');
        $data = [
            'teller'       => [],
            'shop'         => [],
            'method'       => [],
            'consultation' => []
        ];
        if (empty($keyword)) return response()->json($data, 200);

        $tellers = Fortuneteller::select('id', 'number', 'slug', 'name', 'display_name', 'avatar')
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->where(function ($query) use ($keyword) {
                $query->where('name', 'like', "%$keyword%")
                    ->orWhere('id', 'like', "%$keyword%")
                    ->orWhere('display_name', 'like', "%$keyword%")
                    ->orWhere('slug', 'like', "%$keyword%");
            })
            ->orderBy('updated_at', 'DESC')
            ->limit(15)
            ->get();
        $data['teller'] = $tellers;

        $shops = Shop::select('id', 'name', 'slug', 'logo')
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->where(function ($query) use ($keyword) {
                $query->where('name', 'like', "%$keyword%")
                    ->orWhere('id', 'like', "%$keyword%")
                    ->orWhere('slug', 'like', "%$keyword%");
            })
            ->orderBy('updated_at', 'DESC')
            ->limit(15)
            ->get();
        $data['shop'] = $shops;


        $methods = Fortunemethod::select('id', 'name', 'slug', 'top_name', 'logo')
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->where(function ($query) use ($keyword) {
                $query->where('name', 'like', "%$keyword%")
                    ->orWhere('id', 'like', "%$keyword%")
                    ->orWhere('slug', 'like', "%$keyword%")
                    ->orWhere('top_name', 'like', "%$keyword%");
            })
            ->orderBy('updated_at', 'DESC')
            ->limit(15)
            ->get();
        $data['method'] = $methods;


        $consultations = Consultation::select('id', 'name', 'slug')
            ->where('is_activated', true)
            ->where('is_deleted', false)
            ->where(function ($query) use ($keyword) {
                $query->where('name', 'like', "%$keyword%")
                    ->orWhere('id', 'like', "%$keyword%")
                    ->orWhere('slug', 'like', "%$keyword%");
            })
            ->orderBy('updated_at', 'DESC')
            ->limit(15)
            ->get();
        $data['consultation'] = $consultations;

        return response()->json($data, 200);
    }
}
