<?php

use Jaga\Models\BaseModel;

class ReqUmUserEmail extends BaseModel {
    public $id;
    public $um_id;
    public $old_value;
    public $new_value;
    public $verif_code;
    public $status;
    public $created_at;
    public $verified_at;
    public $deleted_at;

    const SECRET = "rqjhuolfxrbwvvsatwciqjzqvpkbitwc";
    const INTERVAL = 60;

    public function initialize() {
        $this->setSchema("jaga");
        $this->setSource("req_um_user_email");
        $this->belongsTo('um_id', UmUser::class, 'um_id');
    }

    public function getSource()
    {
        return 'req_um_user_email';
    }

    public static function reqChange(UmUser $umUser, $newValue) {
        UserHelper::validateEmailAvailability($newValue);

        /** @var ReqUmUserEmail[] $oldReqs */
        $oldReqs = self::find([
            'conditions' => 'um_id = :um_id: and deleted_at is null and status = 0',
            'bind' => [
                'um_id' => $umUser->um_id
            ]
        ]);

        foreach ($oldReqs as $oldReq) {
            if (!$oldReq->validateLastCreate(self::INTERVAL)) {
                throw new CustomErrorException(BaseResponse::INVALID_ACTION, "Anda harus menunggu ".self::INTERVAL." detik sebelum membuat link verifikasi yang baru.");
            }
            $oldReq->deleted_at = date("Y-m-d H:i:s");
            $oldReq->save();
        }

        $model = new ReqUmUserEmail();
        $model->um_id = $umUser->um_id;
        $model->status = 0;
        $model->old_value = $umUser->email;
        $model->new_value = $newValue;
        $model->generateVerifCode();
        if (!$model->save()) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, $model->getMessages());
        }

        return $model->verif_code;
    }

    public static function reqVerify(UmUser $umUser, $email) {
        /** @var ReqUmUserEmail[] $oldReqs */
        $oldReqs = self::find([
            'conditions' => 'um_id = :um_id: and deleted_at is null and status = 0',
            'bind' => [
                'um_id' => $umUser->um_id
            ]
        ]);

        foreach ($oldReqs as $oldReq) {
            if (!$oldReq->validateLastCreate(self::INTERVAL)) {
                throw new CustomErrorException(BaseResponse::INVALID_ACTION, "Anda harus menunggu ".self::INTERVAL." detik sebelum membuat link verifikasi yang baru.");
            }
            $oldReq->deleted_at = date("Y-m-d H:i:s");
            $oldReq->save();
        }

        $model = new ReqUmUserEmail();
        $model->um_id = $umUser->um_id;
        $model->status = 0;
        $model->old_value = $umUser->email;
        $model->new_value = $email;
        $model->generateVerifCode();
        if (!$model->save()) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, $model->getMessages());
        }

        return $model->verif_code;
    }

    public function generateVerifCode() {
        if (empty($this->um_id) || empty($this->old_value) || empty($this->new_value)) {
            throw new CustomErrorException(BaseResponse::UNEXPECTED_ERROR, "Permintaan data tidak lengkap.");
        }

        $o = [
            "um_id" => $this->um_id,
            "old_value" => $this->old_value,
            "new_value" => $this->new_value
        ];

        $this->verif_code = AuthHelper::encryptMessage(json_encode($o), self::SECRET, true);
    }

    public function verifyCode(UmUser $umUser) {
        $verified = false;
        $code = AuthHelper::decryptMessage($this->verif_code, self::SECRET, true);
        $o = json_decode($code, true);
        if (array_key_exists('um_id', $o) && $o['um_id'] == $umUser->um_id) {
            $verified = true;
            $this->verified_at = date("Y-m-d H:i:s");
            $this->status = 1;
            $this->save();
        }

        return $verified;
    }

    /**
     * @param $verifCode
     * @return ReqUmUserEmail
     * @throws CustomErrorException
     */
    public static function findByVerifCode($verifCode) {
        /** @var ReqUmUserEmail $data */
        $data = self::findFirst([
            'conditions' => "verif_code LIKE :verif_code:",
            'bind' => [
                "verif_code" => $verifCode
            ]
        ]);
        if (!$data) {
            throw new CustomErrorException(BaseResponse::DATA_NOT_FOUND, "Kode verifikasi tidak valid.");
        }

        if ($data->status || !empty($data->deleted_at)) {
            throw new CustomErrorException(BaseResponse::INVALID_REQUEST, "Kode verifikasi sudah tidak berlaku.");
        }

        return $data;
    }

    private function validateLastCreate($maxSecondsToCreate) {
        date_default_timezone_set('Asia/Jakarta');
        $now = time();
        $lastCreated = strtotime($this->created_at);
        return ($now - $lastCreated) > $maxSecondsToCreate;
    }
}
