<?php

//namespace Jaga\Controllers;
use Jaga\Models\PAK\PAKQuestionnaire;
use Jaga\Models\PAK\PAKJenisDokumenQuestionnaire;

class PAKJenisDokumenQuestionnaireController extends BaseController
{
    public function onConstruct()
    {
        parent::onConstruct();
        $this->checkIsAuthenticated();
        $this->checkScopes(['pak.manage.questionnaire']);
    }
    
    public function all()
    {
        //$this->checkScopes(['pak.admin']);

        return $this->renderList(true);
    }

    public function index()
    {
        ////$this->checkScopes(['pak.admin']);

        return $this->renderList(false);
    }

    public function renderList($includeDeleted = false)
    {
        $params = $this->validateIndexRequest($this->request->get());

        switch ($includeDeleted) {
            case true:
                $builder = $this->modelsManager
                    ->createBuilder()
                    ->from('Jaga\Models\PAK\PAKJenisDokumenQuestionnaire');
                break;
            
            default:
                $builder = $this->modelsManager
                    ->createBuilder()
                    ->from('Jaga\Models\PAK\PAKJenisDokumenQuestionnaire')
                    ->where('deleted_by IS NULL');
                break;
        }

        if (!empty($params['keyword'])) {
            $builder->andWhere(
                "Jaga\Models\PAK\PAKJenisDokumenQuestionnaire.jenis_dokumen ilike :keyword:", 
                ['keyword' => '%' . $params['keyword'] . '%',]
            );
        }

        if (!empty($params['questionnaire_id'])) {
            $builder->andWhere(
                "Jaga\Models\PAK\PAKJenisDokumenQuestionnaire.questionnaire_id = :questionnaire_id:", 
                ['questionnaire_id' => $params['questionnaire_id'] ]
            );
        }

        $all = $builder->getQuery()->execute();
        $total_record = count($all);
        $rows = $builder
            ->limit($params['limit'])
            ->offset($params['offset'])
            ->getQuery()
            ->execute();

        return new PaginatedResponse(
            $rows, 
            $total_record, 
            $params['limit'], 
            $params['offset']
        );
    }

    public function view($id)
    {
        //$this->checkScopes(['pak.admin']);
        
        $model = $this->findOrThrow($id);
        $result = $model->getDetail();
        return new CollectionPaginatedResponse([$result]);
    }

    public function create()
    {
        //$this->checkScopes(['pak.admin']);

        $rawBody = $this->request->getJsonRawBody(true);
        $params = $this->validateCreateAndUpdateRequest($rawBody);
        $params['created_by'] = $this->userID;

        $model = new PAKJenisDokumenQuestionnaire();
        $model->assign($params);
        $saved = $model->save();

        if (!$saved) {
            $this->throwValidationException($model->getMessages());
        } else {

            return new CollectionPaginatedResponse([$model]);
        }
    }

    public function update($id)
    {
        //$this->checkScopes(['pak.admin']);

        $model = $this->findOrThrow($id);

        $rawBody = $this->request->getJsonRawBody(true);
        $params = $this->validateCreateAndUpdateRequest($rawBody);
        $params['updated_by'] = $this->userID;
        $model->assign($params);
        $saved = $model->save();

        if (!$saved) {
            $this->throwValidationException($model->getMessages());
        } else {

            return new CollectionPaginatedResponse([$model]);
        }
    }

    public function delete($id)
    {
        //$this->checkScopes(['pak.admin']);

        $rawBody = $this->request->getJsonRawBody(true);
        $this->validateDeleteAndRestoreRequest($rawBody, $id);

        $model = $this->findOrThrow($id);

        $deleted = $model->delete($this->userID);

        if (!$deleted) {
            $this->throwValidationException($model->getMessages());
        } else {

            return new CollectionPaginatedResponse([$model]);
        }
    }

    public function destroy($id)
    {
        //$this->checkScopes(['pak.admin']);

        $rawBody = $this->request->getJsonRawBody(true);
        $this->validateDeleteAndRestoreRequest($rawBody, $id);

        $model = $this->findOrThrow($id, true);

        $deleted = $model->forceDelete();

        if (!$deleted) {
            $this->throwValidationException($model->getMessages());
        } else {

            return new CollectionPaginatedResponse([$model]);
        }
    }

    public function restore($id)
    {
        //$this->checkScopes(['pak.admin']);
        
        $rawBody = $this->request->getJsonRawBody(true);
        $this->validateDeleteAndRestoreRequest($rawBody, $id);

        $model = $this->findOrThrow($id, true);

        $restored = $model->restore($this->userID);

        if (!$restored) {
            $this->throwValidationException($model->getMessages());
        } else {

            return new CollectionPaginatedResponse([$model]);
        }
    }

    protected function findOrThrow($id, $deleted = false)
    {
        $model = PAKJenisDokumenQuestionnaire::findFirst($id);

        if (empty($model)) {
            throw new CustomErrorException(
                BaseResponse::INVALID_REQUEST, 
                'Jenis Dokumen Questionnaire Tidak Ditemukan'
            );
        }

        if (!$deleted && !empty($model->deleted_at)) {
            throw new CustomErrorException(
                BaseResponse::INVALID_REQUEST, 
                'Jenis Dokumen Questionnaire Sudah Terhapus'
            );
        }

        return $model;
    }

    protected function validateIndexRequest($request)
    {
        $request['limit'] = array_key_exists('limit', $request) ? $request['limit'] : 6;
        $request['offset'] = array_key_exists('offset', $request) ? $request['offset'] : 0;
        $request['keyword'] = array_key_exists('keyword', $request) ? $request['keyword'] : '';
        $request['questionnaire_id'] = array_key_exists('questionnaire_id', $request) ? $request['questionnaire_id'] : '';
        $request['order_by'] = array_key_exists('order_by', $request) ? strtolower($request['order_by']) : 'id';
        $request['order_direction'] = array_key_exists('order_direction', $request) ? strtolower($request['order_direction']) : 'asc';

        $allowed_order = ['id', 'jenis_dokumen'];
        $allowed_order_direction = ['asc', 'desc'];

        $params = $this->validate(
            $request,
            [
                'limit' => ['validators' => ['digit']],
                'offset' => ['validators' => ['digit']],
                'keyword' => ['validators' => []],
                'questionnaire_id' => ['validators' => []],
                'order_by' => ['validators' =>  [[
                    'name' => 'inclusion_in',
                    'params' => $allowed_order
                ]]],
                'order_direction' => ['validators' =>  [[
                    'name' => 'inclusion_in',
                    'params' => $allowed_order_direction
                ]]]
            ]
        );

        return $params;
    }

    protected function validateCreateAndUpdateRequest($request)
    {
        $rules = [
            'questionnaire_id' => ['validators' => ['required', 'digit']],
            'jenis_dokumen' => ['validators' => [
                'required', 
                [
                    'name' => 'max_string',
                    'params' => 255
                ]
            ]],
            'is_using_doc_info' => ['validators' => []],
        ];

        $params = $this->filterExpectedRequest($request, $rules);

        $questionnaire = PAKQuestionnaire::findFirst($params['questionnaire_id']);

        if (empty($questionnaire)) {
            throw new CustomErrorException(
                BaseResponse::INVALID_REQUEST, 
                'Questionnaire tidak ditemukan'
            );
        }

        if (!empty($questionnaire->deleted_at)) {
            throw new CustomErrorException(
                BaseResponse::INVALID_REQUEST, 
                'Questionnaire sudah tidak aktif'
            );
        }

        return $params;
    }

    /**
     * @params $request post request
     * @params $id get request id
     */
    protected function validateDeleteAndRestoreRequest($request, $id)
    {
        $params = $this->filterExpectedRequest(
            $request, 
            [
                'id' => ['validators' => ['required', 'digit']],
            ]
        );

        if ($params['id'] != $id) {
            throw new CustomErrorException(
                BaseResponse::INVALID_REQUEST, 
                'ID tidak sesuai'
            );
        }

        return $params;
    }
}