<?php defined('SYSPATH') || die('No direct script access.');

class Controller_Handler_Sign extends Controller_Handler
{
    public function before()
    {
        parent::before();
    }

    public function action_in()
    {
        $ok = User::instance()->signIn($_POST['login'], $_POST['password']);
        if (!$ok) $this->fail();
    }

    public function action_up()
    {
        $config = Kohana::$config->load('security.securityPolicy');

        $this->post
            ->rule('login', 'not_empty')
            ->rule('activation_code', 'alpha_numeric')
            ->rule('password', 'min_length', [':value', $config['password']['length']])
            ->rule('confirm_password', 'matches', [':validation', 'confirm_password', 'password'])
            ->rule('email', 'not_empty')
            ->rule('email', 'email');

        if (!$this->post->check())
            $this->fail($this->post->errors('signin'));

        if ($err = User::instance()->signUp($_POST['activation_code'], $_POST['email'], $_POST['login'], $_POST['password']))
            $this->fail(I18n::get($err));
    }

    public function action_remindPassword()
    {
        $this->post->rule('email', 'not_empty')->rule('email', 'email');

        if (!$this->post->check())
            $this->fail('Введенная строка не является <span>e‑mail</span> адресом!');

        if (!Account::doesEmailExist($_POST['email']))
            $this->fail('Пользователь с таким <span>e-mail</span> адресом не зарегистрирован в системе!');

        $myUrl = $_SERVER['HTTP_HOST'];

        // http://gitlab.mmcs.sfedu.ru/it-lab/grade/issues/394
        // чтобы не появлялась целая html-страница в popup
        // здесь выдается только короткое текстовое сообщение
        try {
            Account::createRecoveryRequest($_POST['email'], $myUrl);
        } catch (Exception $exception) {
            $this->fail('Ошибка с кодом ' . $exception->getCode() . ': ' . $exception->getMessage());
        }
    }

    public function action_changePassword()
    {
        $res['success'] = false;

        $config = Kohana::$config->load('security.securityPolicy');

        $this->post->rule('token', 'alpha_numeric')
            ->rule('password', 'min_length', [':value', $config['password']['length']])
            ->rule('confirm_password', 'matches', [':validation', 'confirm_password', 'password']);

        if ($this->post->check()) {
            $token = $_POST['token'];
            if (Account::checkToken($token)) {
                Account::changePasswordByToken($token, $_POST['password']);
                $res['success'] = true;
            }
        }

        if (!$res['success']) {
            $res['errors'] = $this->post->errors('signin');
        }

        $this->response->body(json_encode($res));
    }

    public function action_openidlogin()
    {
        $openid = new OpenID;

        $loginopenid = explode('@', $_GET["loginopenid"])[0];
        // user_role было добавлено для http://gitlab.mmcs.sfedu.ru/it-lab/grade/issues/248
        $user_role = $_GET["user_role"];
        $openid->SetIdentity("https://openid.sfedu.ru/server.php/idpage?user=" . $loginopenid);
        $openid->SetTrustRoot('http://' . $_SERVER["HTTP_HOST"]);
        $openid->SetOptionalFields(['email', 'nickname', 'r61globalkey', 'staff', 'student', 'r61studentid']);
        if ($openid->GetOpenIDServer()) {
            $openid->SetApprovedURL('http://' . $_SERVER["HTTP_HOST"] . Kohana::$base_url . 'handler/sign/openidfinish?user_role='.$user_role);
            $openid->Redirect();
        } else {
            $error = $openid->GetError();
            echo "ERROR CODE: " . $error['code'] . "<br>";
            echo "ERROR DESCRIPTION: " . $error['description'] . "<br>";
        }
    }

    public function action_openidfinish()
    {
        if ($_GET['openid_mode'] == 'id_res') {
            $openid = new OpenID;
            $openid->SetIdentity($_GET['openid_identity']);
            $openid_validation_result = $openid->ValidateWithServer();

            if ($openid_validation_result == true) {
                $this->openid_signIn();
            } elseif ($openid->IsError() == true) {
                $error = $openid->GetError();
                echo 'Ошибка!';
                echo "[" . $error['code'] . "]: " . $error['description'];
            } else {
                echo 'Ошибка!';
                echo "При авторизации что-то пошло не так. Попробуете снова?";
            }
        } elseif ($_GET['openid_mode'] == 'cancel') {
            echo "Вы досрочно прекратили процесс авторизации.";
        }
    }

    private function openid_signIn()
    {
        $isStudent = $_GET["openid_sreg_student"];
        $isStaff = $_GET["openid_sreg_staff"];
        $globalKey = $_GET["openid_sreg_r61globalkey"];
        $studentId = $_GET["openid_sreg_r61studentid"];
        $email = $_GET["openid_sreg_email"];
        // user_role для http://gitlab.mmcs.sfedu.ru/it-lab/grade/issues/248
        $chosen_role = $_GET["user_role"];

        $id = 0;
        $error = null;
        try {
            if ($isStudent && $isStaff) {
                // http://gitlab.mmcs.sfedu.ru/it-lab/grade/issues/248
                if ($chosen_role === 'student') {
                // find student with same ext id
                $openidPrefixes = ["st-","ss-"];
                $emptySpaces = ['',''];
                $inila = strtoupper(str_replace($openidPrefixes, $emptySpaces, $globalKey));
                $extId = Model_Account::getAccountExtIdByInila($inila);
                if ($extId === null || $extId === "") {
                    $id = User::instance()->signInByOpenID($globalKey);
                    if ($id === 0) {
                        if ($studentId) {
                            $key = 'st-'.str_pad($studentId, 9, '0', STR_PAD_LEFT);
                            $id = User::instance()->signInByOpenID($key);
                            if ($id === 0) {
                                $error = "не найдены аккаунты преподавателя или студента!";
                            }
                        } else {
                            $error = "не найдены аккаунты преподавателя или студента!";
                        }
                    }
                } else {
                    $globalKey = 'st-' . $extId;
                    $id = User::instance()->signStudentInByOpenID($globalKey);
                    if ($id === 0) {
                        $id = User::instance()->signInByOpenID($globalKey);
                        if ($id === 0) {
                            $error = "не найдены аккаунты преподавателя или студента!";
                        }
                    }
                }
                } else {
                    $globalKey = str_replace('st-ss-', 'ss-', $globalKey);
                    $id = User::instance()->signInByOpenID($globalKey);
                    if ($id === 0) {
                        $error = "не найден аккаунт преподавателя!";
                    }
                }
            } elseif ($isStudent) {
                $globalKey = 'st-' . str_pad(str_replace('st-', '', $globalKey), 9, '0', STR_PAD_LEFT);
                $id = User::instance()->signStudentInByOpenID($globalKey);
                if ($id === 0) {
                    if ($studentId) {
                        $key = 'st-'.str_pad($studentId, 9, '0', STR_PAD_LEFT);
                        $id = User::instance()->signStudentInByOpenID($key);
                        if ($id === 0) {
                            $error = "не найден аккаунт студента!";
                        }
                    } else {
                        $error = "не найден аккаунт студента!";
                    }
                }
            } elseif ($isStaff) {
                $id = User::instance()->signInByOpenID($globalKey);
                if ($id === 0) {
                    $error = "не найден аккаунт преподавателя!";
                }
            }
        } catch (Exception $e) {
            $error = $e->getMessage();
        } finally {
            Model_Logs::logSigninDetailed($id, $isStaff, $isStudent, $globalKey, $studentId, $error);
        }

        if ($id <= 0) {
            $this->fail("При авторизации произошла ошибка! Обратитесь в службу технической поддержки brs@sfedu.ru. Содержимое ошибки: " . $error);
        }

        $session = Session::instance();
        if ($session['EMail'] != $email) {
            if (Model_Account::changeEMail($id, $email)) {
                $session->set('EMail', $email);
                $session->set('EMailChanged', true);
            } else {
                Log::instance()->add(Log::WARNING, '{0} {1}', array(
                    '{0}' => 'EMAIL_SIGNIN',
                    '{1}' => 'Cannot set email ' . $email . ' for user ' . $globalKey . ' ( ' . $id . ' )',
                ));
            }
        }

        $this->redirect('/');
    }
}