<?php

namespace app\models;

use Yii;
use yii\db\ActiveRecord;
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
use yii\web\IdentityInterface;

class User extends ActiveRecord implements IdentityInterface
{
    public static function tableName()
    {
        return 'user';
    }

    public function behaviors()
    {
        return [
            [
                'class' => TimestampBehavior::class,
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                    ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
                ],
                'value' => new Expression('NOW()'),
            ],
        ];
    }

    public function rules()
    {
        return [
            [['username', 'password', 'email'], 'required'],
            [['username', 'password', 'email', 'totp_secret'], 'string', 'max' => 255],
            [['username'], 'unique'],
            [['email'], 'unique'],
            [['email'], 'email'],
            [['totp_enabled'], 'boolean'],
            [['totp_enabled'], 'default', 'value' => false],
            [['created_at', 'updated_at'], 'safe'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'username' => 'Логин',
            'password' => 'Пароль',
            'email' => 'Email',
            'created_at' => 'Дата создания',
            'updated_at' => 'Дата обновления',
            'totp_secret' => 'Секретный ключ',
            'totp_enabled' => '2FA включена',
        ];
    }

    // ========== IdentityInterface ==========
    public static function findIdentity($id)
    {
        return static::findOne($id);
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        return null;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getAuthKey()
    {
        return null;
    }

    public function validateAuthKey($authKey)
    {
        return false;
    }

    public static function findByUsername($username)
    {
        return static::findOne(['username' => $username]);
    }

    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password);
    }

    public function setPassword($password)
    {
        $this->password = Yii::$app->security->generatePasswordHash($password);
    }

    // ========== Методы для 2FA ==========

    /**
     * Проверка, включена ли 2FA
     */
    public function isOtpEnabled()
    {
        return (bool)$this->totp_enabled;
    }

    /**
     * Включение 2FA (сохранение секрета)
     */
    public function enableOtp($secret)
    {
        $this->totp_secret = $secret;
        $this->totp_enabled = true;
        return $this->save();
    }

    /**
     * Отключение 2FA
     */
    public function disableOtp()
    {
        $this->totp_secret = null;
        $this->totp_enabled = false;
        return $this->save();
    }

    /**
     * Генерация секретного ключа и QR-кода
     */
    public function generateSecret()
    {
        $auth = Yii::$app->googleAuthenticator;

        // Генерация 16-символьного секрета
        $secret = strtoupper(substr(md5(uniqid(rand(), true)), 0, 16));

        // Устанавливаем секрет в компонент
        $auth->setSecret($secret);

        // Получаем URL для QR-кода (Google Charts API)
        $qrCodeUrl = $auth->getQRCodeGoogleUrl($this->username, $secret);

        return [
            'secret' => $secret,
            'qr' => $qrCodeUrl,
        ];
    }

    /**
     * Проверка кода из Google Authenticator
     */
    public function verifyCode($code, $secret = null)
    {
        $secretToCheck = $secret ?: $this->totp_secret;

        if (empty($secretToCheck) || empty($code)) {
            return false;
        }

        $auth = Yii::$app->googleAuthenticator;

        $auth->setSecret($secretToCheck);

        return $auth->verifyCode($code, 8);
    }

    /**
     * Альтернативная проверка с увеличенным допуском (если время на сервере плавает)
     */
    public function verifyCodeWithLeeway($code, $secret = null, $leeway = 5)
    {
        $auth = Yii::$app->googleAuthenticator;
        $secretToCheck = $secret ?: $this->totp_secret;

        if (empty($secretToCheck) || empty($code)) {
            return false;
        }

        $auth->setSecret($secretToCheck);
        return $auth->verifyCode($code, $leeway);
    }
}