<?php

namespace frontend\controllers;

use core\entities\post\PostType;
use core\forms\post\PostCommentForm;
use core\repositories\post\read\PostCategoryReadRepository;
use core\repositories\post\read\PostReadRepository;
use core\repositories\post\read\PostTagReadRepository;
use core\services\post\PostCommentService;
use frontend\components\FrontendController;
use Yii;
use yii\data\ActiveDataProvider;
use yii\web\NotFoundHttpException;
use yii\filters\AccessControl;

class PostController extends FrontendController
{
    public $layout = 'post';

    private $service;
    private $posts;
    private $categories;
    private $tags;

    public function __construct(
        $id,
        $module,
        PostCommentService $service,
        PostReadRepository $posts,
        PostCategoryReadRepository $categories,
        PostTagReadRepository $tags,
        $config = []
    )
    {
        parent::__construct($id, $module, $config);
        $this->service = $service;
        $this->posts = $posts;
        $this->categories = $categories;
        $this->tags = $tags;
    }

	public function behaviors(): array
	{
		return [
			'access' => [
				'class' => AccessControl::className(),
				'rules' => [
					[
						'actions' => ['index', 'category', 'tag', 'post'],
						'allow' => true,
						'roles' => ['Posts'],
					],
					[
						'actions' => ['comment'],
						'allow' => true,
						'roles' => ['Comments'],
					],
					[    // all the action are accessible to admin
						'allow' => true,
						'roles' => ['admin'],
					],
				],
			],
		];
	}

	/**
	 * @param $tid
	 *
	 * @return string
	 * @throws NotFoundHttpException
	 */
    public function actionIndex($tid)
    {
	    $type = $this->findType($tid);
	    /* @var $dataProvider ActiveDataProvider */
        $dataProvider = $this->posts->getAll($type->id);
	    $dataProvider->pagination->pageSize = 10;

        $this->layout = $type->name;
        return $this->render($type->name . '/index', [
            'dataProvider' => $dataProvider,
	        'type' => $type,
        ]);
    }

	/**
	 * @param $id
	 * @param $tid
	 *
	 * @return string
	 * @throws NotFoundHttpException
	 */
    public function actionCategory($id, $tid)
    {
	    if (!$category = $this->categories->find($id)) {
		    throw new NotFoundHttpException('The requested page does not exist.');
	    }
        $type = $this->findType($tid);

        $dataProvider = $this->posts->getAllByCategory($category);

        return $this->render($type->name . '/category', [
            'category' => $category,
            'dataProvider' => $dataProvider,
	        'type' => $type,
        ]);
    }

    /**
     * @param $id
     * @return mixed
     * @throws NotFoundHttpException
     */
    public function actionTag($id)
    {
        if (!$tag = $this->tags->find($id)) {
            throw new NotFoundHttpException('The requested page does not exist.');
        }

        $dataProvider = $this->posts->getAllByTag($tag);

        return $this->render('tag', [
            'tag' => $tag,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * @param $id
     * @return mixed
     * @throws NotFoundHttpException
     */
    public function actionPost($id)
    {
        if (!$post = $this->posts->find($id)) {
            throw new NotFoundHttpException('The requested page does not exist.');
        }

        $type = $this->findType($post->type_id);

	    $this->layout = $type->name;

        return $this->render($type->name . '/post', [
            'post' => $post,
	        'type' => $type,
        ]);
    }

    /**
     * @param $id
     * @return mixed
     * @throws NotFoundHttpException
     */
    public function actionComment($id)
    {
        if (!$post = $this->posts->find($id)) {
            throw new NotFoundHttpException('The requested page does not exist.');
        }

        $form = new PostCommentForm();

        if ($form->load(Yii::$app->request->post()) && $form->validate()) {
            try {
                $comment = $this->service->create($post->id, Yii::$app->user->id, $form);
                return $this->redirect(['post', 'id' => $post->id, '#' => 'comment_' . $comment->id]);
            } catch (\DomainException $e) {
                Yii::$app->errorHandler->logException($e);
                Yii::$app->session->setFlash('error', $e->getMessage());
            }
        }

        return $this->render('comment', [
            'post' => $post,
            'model' => $form,
        ]);
    }

	protected function findType($id): PostType
	{
		if (($type = PostType::findOne($id)) !== null) {
			return $type;
		}
		throw new NotFoundHttpException('The requested page does not exist.');
	}
}