<?php

namespace App\Http\Controllers;

use App\Http\Resources\ProductItemDetailResource;
use App\ProductDetail;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use App\Http\Resources\ProductResource;
use App\Http\Resources\ProductDetailResource;
use App\Product;
use App\Category;
use DB;

class ProductController extends Controller
{
    const ITEM_PER_PAGE = 25;

    public function index(Request $request)
    {
        $searchParams = $request->all();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $keyword = Arr::get($searchParams, 'keyword', '');
        $status = Arr::get($searchParams, 'status', '');
        $categoryId = Arr::get($searchParams, 'categoryId', '');
        $subCategoryId = Arr::get($searchParams, 'subCategoryId', '');
        $manufacturerId = Arr::get($searchParams, 'manufacturerId', '');
        $priceFrom = Arr::get($searchParams, 'priceFrom', '');
        $priceTo = Arr::get($searchParams, 'priceTo', '');

        $list = Product::select('*')->isPublished();

        if (!empty($keyword)) {
            $list->where(function ($query) use ($keyword) {
                $query->where('name', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('price_from', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('price_to', 'LIKE', '%' . $keyword . '%')
                    ->orWhere('discount', 'LIKE', '%' . $keyword . '%');
            });
        }

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

        if (!empty($categoryId) || !empty($subCategoryId)) {
            $searchCategoryId = $subCategoryId;
            if ($searchCategoryId == null || $searchCategoryId == "") $searchCategoryId = $categoryId;

            if (!empty($searchCategoryId)) {
                $category = Category::where('id', $searchCategoryId)->first();
                if (isset($category)) {
                    $categories = Category::select('id', 'parent_id')
                        ->where('id', '!=', $category->parent_id)
                        ->where('id', '!=', $searchCategoryId)
                        ->where('parent_id', '!=', 0)
                        ->whereNotNull('parent_id')
                        ->get();

                    $listIds = $this->detectChildCategoryId($categories, $searchCategoryId);
                    $listIds[] = $category->id;
                    $list->whereIn('category_id', $listIds);
                }
            }
        }

        if (!empty($priceFrom)) {
            $list->where('price_from', '>=', $priceFrom);
        }

        if (!empty($priceTo)) {
            $list->where('price_from', '<=', $priceTo);
        }

        if ($status != '') {
            $list->where('is_activated', $status);
        }

        $list->orderBy('id', 'DESC');

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

    public function top(Request $request)
    {
        $searchParams = $request->all();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $list = Product::select('*')->isPublished()->orderBy('id', 'DESC');

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

    public function show($id = 0)
    {
        $product = Product::select('*')
            ->isPublished()
            ->where('id', $id)
            ->first();

        if (!isset($product)) return response()->json(['data' => null, 'errors' => 'Product is invalid'], 200);

        return new ProductDetailResource($product);
    }

    public function estimateCheck(Request $request, $id = 0)
    {
        $product = Product::select('*')
            ->isPublished()
            ->where('id', $id)
            ->first();

        if (!isset($product)) return response()->json(['data' => null, 'errors' => 'Product is invalid'], 200);

        $params = $request->all();
        $listOptionIds = [];
        foreach ($params['options'] as $item) {
            $listOptionIds[] = $item['value'];
        }

        $productDetail = ProductDetail::select(
            'product_details.id as id',
            'product_details.product_id as product_id',
            'product_details.sku as sku',
            'product_details.code as code',
            'product_details.price as price',
            'product_option_details.id as option_detail_id',
            'product_option_details.name as option_detail_name'
        )
            ->join('product_detail_option_details', 'product_details.id', '=', 'product_detail_option_details.product_detail_id')
            ->join('product_option_details', 'product_detail_option_details.product_option_detail_id', '=', 'product_option_details.id')
            ->where('product_details.product_id', $product->id)
            ->whereIn('product_option_details.id', $listOptionIds)
            ->get();

        $list = [];
        foreach ($productDetail as $item) {
            if (!isset($list[$item->id])) {
                $list[$item->id] = [
                    'id'         => $item->id,
                    'product_id' => $item->product_id,
                    'sku'        => $item->sku,
                    'code'       => $item->code,
                    'price'      => $item->price,
                    'options'    => [],
                ];
            }
            $list[$item->id]['options'][] = $item->option_detail_id;
        }

        $checkDetailId = '';
        $checkDetailCode = '';
        foreach ($list as $item) {
            if (count($item['options']) == count($listOptionIds)) {
                $checkMatch = true;
                foreach ($listOptionIds as $oId) {
                    if (!in_array($oId, $item['options'])) $checkMatch = false;
                }
                if ($checkMatch) {
                    $checkDetailId = $item['id'];
                    $checkDetailCode = $item['code'];
                    break;
                }
            }
        }

        $status = 'error';
        $rs = [];
        if ($checkDetailCode != null && $checkDetailCode != "") {
            $status = 'success';
            $rs = [
                'id'          => $checkDetailId,
                'code'        => $checkDetailCode,
                'purchase_id' => $params['purchase_id'],
            ];
        }

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

    public function estimateShow($id = 0, $code = '')
    {
        $product = Product::select('*')
            ->isPublished()
            ->where('id', $id)
            ->first();

        $productDetail = ProductDetail::where('product_id', $id)
            ->where('code', $code)
            ->first();

        if (!isset($product) || !isset($productDetail)) return response()->json(['status' => 'error', 'data' => null, 'errors' => 'Product is invalid'], 200);

        return new ProductItemDetailResource($productDetail);
    }

    public function ranking(Request $request)
    {
        //$searchParams = $request->all();
        //$limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);

        $listA = Product::select('id', 'category_id', 'name', 'slug', 'sku', 'discount', 'description', 'image', 'note', 'policy', 'possible_delivery_time', 'regular_price_from', 'regular_price_to', 'price_from', 'price_to')
            ->isPublished()
            ->orderBy('id', 'DESC')
            ->limit(6)
            ->get();

        $listB = Product::select('id', 'category_id', 'name', 'slug', 'sku', 'discount', 'description', 'image', 'note', 'policy', 'possible_delivery_time', 'regular_price_from', 'regular_price_to', 'price_from', 'price_to')
            ->with('category')
            ->isPublished()
            ->orderBy('id', 'DESC')
            ->limit(12)
            ->get();

        $listC = Product::select('id', 'category_id', 'name', 'slug', 'sku', 'discount', 'description', 'image', 'note', 'policy', 'possible_delivery_time', 'regular_price_from', 'regular_price_to', 'price_from', 'price_to')
            ->isPublished()
            ->orderBy('id', 'DESC')
            ->limit(12)
            ->get();

        $listD = Product::select('id', 'category_id', 'name', 'slug', 'sku', 'discount', 'description', 'image', 'note', 'policy', 'possible_delivery_time', 'regular_price_from', 'regular_price_to', 'price_from', 'price_to')
            ->isPublished()
            ->orderBy('id', 'DESC')
            ->limit(12)
            ->get();

        return response()->json(['data' => [
            'list_1' => $listA,
            'list_2' => $listB,
            'list_3' => $listC,
            'list_4' => $listD,
        ]], 200);
    }

    public function rankingCategory(Request $request, $id = 0) {
        $searchParams = $request->all();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);

        $list = Product::select('products.*', DB::raw('count(products.id) as total_sale'))
            ->join('order_details', 'order_details.product_id', '=', 'products.id')
            ->where('products.is_deleted', false)
            ->where('products.is_activated', true)
            ->groupBy('products.id');

        if ($id != null && $id != "" && $id != 0) {
            $category = Category::where('id', $id)->first();
            if (isset($category)) {
                $categories = Category::select('id', 'parent_id')
                    ->where('id', '!=', $category->parent_id)
                    ->where('id', '!=', $id)
                    ->where('parent_id', '!=', 0)
                    ->whereNotNull('parent_id')
                    ->get();

                $listIds = $this->detectChildCategoryId($categories, $id);
                $listIds[] = $category->id;
                $list->whereIn('products.category_id', $listIds);
            }
        }

        $list->orderBy('total_sale', 'DESC')->orderBy('products.id', 'ASC');

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

    public function rankingManufacturer(Request $request, $id = 0) {
        $searchParams = $request->all();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $list = Product::select('*')
            ->isPublished()
            ->where('manufacturer_id', $id)
            ->whereNotNull('rank')
            ->orderBy('rank', 'DESC')
            ->orderBy('updated_at', 'DESC');

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

    private function detectChildCategoryId($list = [], $categoryId = '')
    {
        $listIds = [];
        foreach ($list as $item) {
            if ($item->parent_id == $categoryId) {
                $listIds[] = $item->id;
                $subIds = $this->detectChildCategoryId($list, $item->id);
                $listIds = array_merge($listIds, $subIds);
            }
        }

        return $listIds;
    }
}
