<?php

namespace App\Http\Controllers\Admin;


use App\Model\Cuisine;
use App\Model\Tag;
use Illuminate\Http\Request;
use App\Http\Requests\StoreArticle;
use Illuminate\Support\Str;
use Utils;
use Validator;
use Illuminate\Support\Facades\DB;

use App\Model\Category;
use App\Model\Article;
use App\Model\Article\ArticlePhoto;

use App\Http\Requests\StorePhoto;

class ArticleController extends BaseController
{


    public function __construct()
    {
        parent::__construct();
//        $this->authorizeResource(Article::class);
    }


    use Photos;

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {

//        $artisan = Artisan::call('route:list');
//        dd(Artisan::output());

        if ($request->category_id) {
            $category = Category::find($request->category_id);
        } else {
            $category = null;
        }

        $articles = $request->category_id ? $category->articles() : (new Article)->newQuery();

        $parent = null;
        if ($request->get('parent_id')) {
            $articles->whereHas('category', function ($q) {
                $q->where('parent_id', request('parent_id'));
            });
            $parent = Category::find($request->get('parent_id'));
        }

        // do we have a search here?
        if ($q = $request->get('q')) {
            $articles->search($q);
        }

        if ($code = $request->get('code')) {
            $articles->where('code', 'like', '%' . $code . '%');
        }


        $articles->with('photo')
            ->with('category', 'user')
            ->when($request->get('root_id'), function ($q, $category_id) {

                $children = Category::where('parent_id', $category_id)->get()->pluck('id')->toArray();

                $q->whereIn('category_id', array_merge([
                    $category_id
                ], $children));
            })
            // use array_filter cos for example, if camapign_id= is passed then wrong filtering will occur
            ->where(array_filter($request->except([
                'q',
                'code',
                'page',
                'category_id',
                'parent_id',
                'order_by',
                'order_direction',
                'sortable',
                'root_id',
            ])));


        $base_categories = Category::when(request('parent_id', request('root_id')), function ($q, $parent_id) {
            $q->where(compact('parent_id'));
            $q->orWhere('id', $parent_id);
        })->get();

        $categories = Category::tree($base_categories);


        if ($request->get('sortable')) {
            $articles = $articles
                ->featured()
                ->priority()
                ->limit(24)
                ->get();
            return view('admin.article.featured.index', compact('articles'));
        }

        $articles = $articles->orderBy($request->get('order_by') ?: 'id', $request->get('order_direction') ?: 'desc')
            ->paginate(config('pagination.admin.items_per_page'))
            ->appends($request->except('page'));


        return view('admin.article.index', compact('articles', 'categories', 'category', 'parent'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create(Article $article)
    {
        if ($category_id = request('category_id')) {
            $article->category_id = $category_id;
        }
        return $this->edit($article);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @return \Illuminate\Http\Response
     */
    public function store(StoreArticle $request, Article $article)
    {
        return $this->update($request, $article);
    }

    /**
     * Display the specified resource.
     *
     * @param \App\Model\Article $article
     * @return \Illuminate\Http\Response
     */
    public function show(Article $article)
    {
        dd($article);
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param \App\Model\Article $article
     * @return \Illuminate\Http\Response
     */
    public function edit(Article $article)
    {

        // if we have a subcategory, we show all root categories, so user can change the parent category.
        // $categories = Category::root()->ordered()->get();

        $category = $article->category;
        if (empty($category) && request('category_id')) {
            $category = Category::find(request('category_id'));
        }

        $base_categories = Category::orderBy('name')->get();
        $categories = Category::tree($base_categories)->when(request('parent_id'), function ($collection, $id) {
            return $collection->where('id', $id);
        })
            ->when($category && $category->parent_id, function ($collection) use ($category) {
                return $collection->where('id', $category->parent_id);
            })
            ->when($category && !$category->parent_id, function ($collection) use ($category) {
                return $collection->where('id', $category->id);
            })
            ->where('can_create_articles', true);

        $item = &$article;

        if ($article->isRecipe()) {
            $cuisines = Cuisine::orderBy('slug')->get();
        } else {
            $cuisines = [];
        }


        return response()->view('admin.article.edit', compact('article', 'item', 'categories', 'cuisines'))
            ->header("pragma", "no-cache")
            ->header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");

    }

    /**
     * Update the specified resource in storage.
     *
     * @param \Illuminate\Http\Request $request
     * @param \App\Model\Article $article
     * @return \Illuminate\Http\Response
     */
    public function update(StoreArticle $request, Article $article)
    {
        try {
            DB::beginTransaction();

            if ($article->exists) {
                $tags = collect($request->get('tags'))->map(function ($item) {
                    $item = trim($item);
                    return Tag::firstOrCreate([
                        'slug' => Str::slug($item),
                    ], [
                        'name' => $item,
                    ])->id;
                })->unique();

                $article->tags()->sync($tags->toArray());
            }

            // go save the article first (when new article, we need this for category assoc)
            $article->fill($request->except('categories', 'files', 'tags'))
                ->save();

            if (!empty($article->params->cuisine)) {
                Cuisine::firstOrCreate([
                    'name' => $article->params->cuisine,
                    'is_active' => 1,
                ]);
            }


            DB::commit();
        } catch (\Exception $e) {
            DB::rollback();
            /* Transaction failed. */
            throw new $e;
        }

        if ($request->isXmlHttpRequest()) {
            return 1;
        }
//        if (count($request->all()) <= 5) {
//            return back();
//        }

        // done
        return redirect(route('admin.articles.edit', $article));
    }


    /**
     * Remove the specified resource from storage.
     *
     * @param \App\Model\Article $article
     * @return \Illuminate\Http\Response
     */
    public function destroy(Article $article)
    {
        $article->delete();

        return back();
    }


    /**
     * Expects an array of articles (WHERE... IN)
     * and other keys which are all passed to SET.
     */
    public function bulkUpdate()
    {
        $articles = request()->get('articles');
        $fields = request()->except('articles', '_token');

        Article::whereIn('id', $articles)->update($fields);
    }

    public function photo(Article $article, StorePhoto $request)
    {
        return $this->process($article, $request, ArticlePhoto::class);
    }

    public function photos(Article $article)
    {
        if (request('render_as_html')) {
            return view('admin.article.recipe.photos', [
                'article' => $article,
                'photos' => $this->list($article)
            ]);
        }
        return $this->list($article);
    }

    /**
     * Article  search
     *
     * @param Request $request
     * @return type
     */
    public function search(Request $request)
    {
        $items = [];
        if (strlen($request->get('q')) >= 1) {
            // filter the categories boy.
            $items = Article::where(function ($q) use ($request) {
                $q->where('name', 'like', '%' . $request->get('q') . '%')
                    // @todo do this only if integer is in query.
                    ->orWhere('id', '=', (int)$request->get('q'));
            })
                ->where('id', '!=', $request->id)
                ->limit(100)
                ->get();
            // we are interested only in this format
            $items = $items->map(function ($item) {
                return [
                    'id' => $item->id,
                    'photo' => $item->getThumbUrl(),
                    'name' => $item->name,
                ];
            });
        }
        // feed the troll
        return response()->json($items);
    }

    public function priority(Request $request)
    {
        $items = $request->get('priority');

        foreach ($items as $item) {
            $article = Article::find($item['id']);
            $article->priority = $item['priority'];
            if ($article->id == $request->get('current_id')) {
                $article->is_manually_prioritized = 1;
            } elseif ($item['priority'] >= config('featured.max_manually_prioritized')) {
                $article->is_manually_prioritized = 0;
            }
            $article->save();
        }
    }

    public function ingredientAdd(Request $request, Article $article, $step_category_index)
    {
        $ingredients = $request->get('ingredients');

        // add new ingredient
        if (empty($ingredients[$step_category_index]['items'])) {
            $ingredients[$step_category_index]['items'] = [];
        }

        $ingredients[$step_category_index]['items'][] = '';

        $request->merge([
            'ingredients' => $ingredients,
        ]);

        $article->fill($request->all())->save();

//        $article->refresh();

        return view('admin.article.recipe.ingredients', [
            'ingredient_categories' => $article->ingredients,
            'article' => $article,
        ]);
    }

    public function ingredientDelete(Request $request, Article $article, $step_category_index, $step_index)
    {
        $ingredients = $request->get('ingredients');

        // remove requested step.
        unset($ingredients[$step_category_index]['items'][$step_index]);

        // if no steps left, remove whole category.
        if (count($ingredients[$step_category_index]['items']) == 0) {
            unset($ingredients[$step_category_index]);
        }

        $request->merge([
            'ingredients' => $ingredients,
        ]);

        $article->fill($request->all())->save();

//        $article->refresh();

        return view('admin.article.recipe.ingredients', [
            'article' => $article,
            'ingredient_categories' => $article->ingredients,
        ]);
    }

    public function ingredientNewCategory(Request $request, Article $article)
    {
        $article->fill($request->all())->save();

        if (!is_array($article->ingredients)) {
            $article->ingredients = [];
        }

        $ingredients = $article->ingredients;
        $ingredients[] = [
            'name' => '',
            'items' => [
                '',
//                '',
            ],
        ];
        $article->ingredients = $ingredients;

        $article->save();

//        $article->refresh();

        return view('admin.article.recipe.ingredients', [
            'ingredient_categories' => $article->ingredients,
            'article' => $article,
        ]);
    }


    public function stepAdd(Request $request, Article $article, $step_category_index)
    {
        $steps = $request->get('steps');

        // add new step
        if (empty($steps[$step_category_index]['steps'])) {
            $steps[$step_category_index]['steps'] = [];
        }
        $steps[$step_category_index]['steps'][] = [
            'filename' => '',
            'text' => '',
        ];

        $request->merge([
            'steps' => $steps,
        ]);

        $article->fill($request->all())->save();

//        $article->refresh();

        return view('admin.article.recipe.steps', [
            'add_step' => true,
            'step_categories' => $article->steps,
            'article' => $article,
        ]);
    }

    public function stepDelete(Request $request, Article $article, $step_category_index, $step_index)
    {
        $steps = $request->get('steps');

        // remove requested step.
        unset($steps[$step_category_index]['steps'][$step_index]);

        // if no steps left, remove whole category.
        if (count($steps[$step_category_index]['steps']) == 0) {
            unset($steps[$step_category_index]);
        }

        $request->merge([
            'steps' => $steps,
        ]);

        $article->fill($request->all())->save();

//        $article->refresh();

        return view('admin.article.recipe.steps', [
            'article' => $article,
            'step_categories' => $article->steps,
        ]);
    }

    public function stepNewCategory(Request $request, Article $article)
    {
        $article->fill($request->all())->save();

        if (!is_array($article->steps)) {
            $article->steps = [];
        }

        $steps = $article->steps;
        $steps[] = [
            'name' => '',
            'steps' => [
                [
                    'filename' => '',
                    'text' => '',
                ],
                [
                    'filename' => '',
                    'text' => '',
                ]
            ],
        ];
        $article->steps = $steps;

        $article->save();

//        $article->refresh();

        return view('admin.article.recipe.steps', [
            'step_categories' => $article->steps,
            'article' => $article,
        ]);
    }

    public function stepPhoto(Request $request, Article $article, $step_category_index, $step_index)
    {
        $steps = $request->get('steps');

        // set photo for the step.
        $steps[$step_category_index]['steps'][$step_index]['filename'] = $request->get('filename');

        $request->merge([
            'steps' => $steps,
        ]);

        $article->fill($request->all())->save();

//        $article->refresh();

        return view('admin.article.recipe.steps', [
            'article' => $article,
            'step_categories' => $article->steps,
        ]);
    }

}
