<?php

namespace App\Http\Controllers\Admin;

use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Resources\Admin\ArticleCategoryResource;
use App\ArticleCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Validator;

/**
 * Class ArticleCategoryController
 *
 * @package App\Http\Controllers\Admin
 */
class ArticleCategoryController extends Controller
{
    const ITEM_PER_PAGE = 100;

    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', '');

        $type = Arr::get($searchParams, 'type', '');
        $list = ArticleCategory::where('is_deleted', false);

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

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

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

        $list->orderBy('position')->orderBy('id');

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

    public function all(Request $request)
    {
        $searchParams = $request->all();
        $limit = Arr::get($searchParams, 'limit', static::ITEM_PER_PAGE);
        $type = Arr::get($searchParams, 'type', '');
        $list = ArticleCategory::select('id', 'name', 'type', 'slug', 'parent_id')
            ->where('is_deleted', false)
            ->where('is_activated', true);

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

        $list->orderBy('position')
            ->orderBy('id');

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

    public function available(Request $request)
    {
        $ignoreId = $request->get('ignoreId', null);
        $type = $request->get('type', '');
        $list = ArticleCategory::select('id', 'name', 'type', 'slug', 'parent_id')
            ->where('is_deleted', false)
            ->where('is_activated', true);

        if ($ignoreId) {
            $list->where('id', '!=', $ignoreId);
        }

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

        $list->orderBy('position')->orderBy('id');

        return ArticleCategoryResource::collection($list->get());
    }

    public function nested(Request $request)
    {
        $ignoreId = $request->get('ignoreId', null);
        $type = $request->get('type', '');
        $categories = ArticleCategory::select('id', 'name', 'type', 'slug', 'parent_id')
            ->where('is_deleted', false)
            ->where('is_activated', true);

        if ($ignoreId) {
            $categories->where('id', '!=', $ignoreId);
        }

        if (!empty($type)) {
            $categories->where('type', $type);
        }

        $categories = $categories->orderBy('position')->orderBy('id')->get();

        $nestedData = $this->buildNestedArray($categories->toArray());

        return response()->json(['data' => $nestedData]);
    }

    private function buildNestedArray($categories, $parent_id = 0)
    {
        $nested = [];

        foreach ($categories as $category) {
            if ($category['parent_id'] == $parent_id) {
                $children = $this->buildNestedArray($categories, $category['id']);
                $nested[] = [
                    'value' => $category['id'],
                    'label' => $category['name'],
                    'children' => $children
                ];
            }
        }

        return $nested;
    }

    public function show($id = 0)
    {
        $category = ArticleCategory::where('is_deleted', false)->where('id', $id)->first();
        if (!isset($category)) return response()->json(['errors' => __('messages.category_not_valid')], 403);

        return new ArticleCategoryResource($category);
    }

    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => ['required'],
            'slug' => ['required'],
            'is_activated' => ['required']
        ]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $params = $request->all();

        $articleCategory = ArticleCategory::create([
            'name' => trim($params['name']),
            'type' => isset($params['type']) ? trim($params['type']) : 'article',
            'slug' => Helper::slug(trim($params['slug'])),
            'parent_id' => isset($params['parent_id']) ? $params['parent_id'] : 0,
            'description' => isset($params['description']) ? trim($params['description']) : '',
            'position' => isset($params['position']) ? $params['position'] : 0,
            'is_activated' => ($params['is_activated'] === true) ? 1 : 0,
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s')
        ]);

        return response()->json([
            'status' => 'success',
            'id' => $articleCategory->id,
        ], 200);
    }

    public function update(Request $request, $id = 0)
    {
        $validator = Validator::make($request->all(), [
            'name' => ['required'],
            'slug' => ['required'],
            'is_activated' => ['required']
        ]);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $articleCategory = ArticleCategory::where('is_deleted', false)->where('id', $id)->first();
        if (!isset($articleCategory)) return response()->json(['errors' => __('messages.category_not_valid')], 403);
        $params = $request->all();

        $articleCategory->update([
            'name' => trim($params['name']),
            'type' => isset($params['type']) ? trim($params['type']) : $articleCategory->type,
            'slug' => Helper::slug(trim($params['slug'])),
            'parent_id' => isset($params['parent_id']) ? $params['parent_id'] : 0,
            'description' => isset($params['description']) ? trim($params['description']) : '',
            'position' => isset($params['position']) ? $params['position'] : 0,
            'is_activated' => ($params['is_activated'] === true) ? 1 : 0,
            'updated_at' => date('Y-m-d H:i:s')
        ]);

        return response()->json([
            'status' => 'success',
            'id' => $articleCategory->id,
        ], 200);
    }

    public function destroy($id = 0)
    {
        $articleCategory = ArticleCategory::where('is_deleted', false)->where('id', $id)->first();
        if (!isset($articleCategory)) response()->json(['error' => __('messages.cannot_delete_category')], 403);

        try {
            $articleCategory->update(['is_deleted' => true]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }

        return response()->json(null, 204);
    }

    public function destroyMultiple(Request $request)
    {
        $validator = Validator::make($request->all(), ['ids' => 'required']);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $listIds = $request->get('ids', []);
        $categories = ArticleCategory::where('is_deleted', false)->whereIn('id', $listIds)->get();
        if ($categories->count() <= 0) response()->json(['error' => __('messages.category_is_invalid')], 403);
        try {
            ArticleCategory::where('is_deleted', false)->whereIn('id', $listIds)->update(['is_deleted' => true]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }

        return response()->json(null, 204);
    }

    public function activateMultiple(Request $request)
    {
        $validator = Validator::make($request->all(), ['ids' => 'required']);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $listIds = $request->get('ids', []);
        $categories = ArticleCategory::where('is_deleted', false)->whereIn('id', $listIds)->get();
        if ($categories->count() <= 0) response()->json(['error' => __('messages.category_is_invalid')], 403);
        try {
            ArticleCategory::where('is_deleted', false)->whereIn('id', $listIds)->update(['is_activated' => true]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }

        return response()->json(null, 204);
    }

    public function deactivateMultiple(Request $request)
    {
        $validator = Validator::make($request->all(), ['ids' => 'required']);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $listIds = $request->get('ids', []);
        $categories = ArticleCategory::where('is_deleted', false)->whereIn('id', $listIds)->get();
        if ($categories->count() <= 0) response()->json(['error' => __('messages.category_is_invalid')], 403);
        try {
            ArticleCategory::where('is_deleted', false)->whereIn('id', $listIds)->update(['is_activated' => false]);
        } catch (\Exception $ex) {
            response()->json(['error' => $ex->getMessage()], 403);
        }

        return response()->json(null, 204);
    }

    public function position(Request $request)
    {
        $validator = Validator::make($request->all(), ['data' => 'required']);
        if ($validator->fails()) return response()->json(['errors' => $validator->errors()], 403);
        $items = $request->get('data', []);
        if (count($items) <= 0) return response()->json(['error' => __('messages.data_is_invalid')], 403);

        try {
            foreach ($items as $item) {
                if (isset($item['id']) && isset($item['position'])) {
                    ArticleCategory::where('id', $item['id'])->update(['position' => $item['position']]);
                }
            }
        } catch (\Exception $ex) {
            return response()->json(['error' => $ex->getMessage()], 403);
        }

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