<?php

/**
 * Class ProfileModel
 */
class ProfileModel extends Cf_Model
{
    const USER_URL = '/user/%s';
    const ME_URL = '/me';
    private $pdo;

    const BUILD_APP_OPENED_KEY = 'build_app_opened';
    const GROUPS_APP_OPENED_KEY = 'groups_app_opened';
    const FIRST_lOGIN_AFTER_RESET_KEY = 'first_login_after_reset';

    public function __construct()
    {
        $this->pdo = $this->db->db_connect();
    }

    /**
     * @param $username
     * @return array
     */
    public function getProfileData(string $username)
    {
        $profileData = json_decode(
            $this->getRestClient()->get(sprintf(self::USER_URL, $username)),
            JSON_OBJECT_AS_ARRAY
        );
        
        $result = isset($profileData['data']) ? $profileData['data'][0] : [];

        $isVerificationNeeded = json_decode(
            $this->getRestClient()->get('/2fa/verification-needed'),
            JSON_OBJECT_AS_ARRAY
        );
        
        if (isset($isVerificationNeeded['result'])) {
            $result['is2FaVerificationNeeded'] = $isVerificationNeeded['result'];
        }
        
        return $result;
    }

    /**
     * @return array
     */
    public function getTimezoneList()
    {
        //get time zones from postgres
        $timeZones = $this->db->query('SELECT * FROM pg_timezone_names WHERE name LIKE \'%/%\' ORDER BY name')->result_array();
        $result = [];
        foreach ($timeZones as $tz) {
            list($continent, $city) = explode('/', $tz['name']);

            $utcOffset = $this->convertUtcOffset($tz['utc_offset']);
            $result[$continent][] = [
                'label' => $city . " (GMT $utcOffset)",
                'value' => $tz['name']
            ];
        }
        return $result;
    }

    /**
     * @param $name
     * @return array
     */
    public function getTimeZone($name)
    {
        $timeZone = $this->db->like('name', $name)->get('pg_timezone_names')->row_array();

        $utcOffset = $this->convertUtcOffset($timeZone['utc_offset']);
        $result = [
            'label' => $timeZone['name'] . " (GMT $utcOffset)",
            'value' => $timeZone['name'],
            'offset' => $utcOffset,
            'minutesOffset' => $this->convertOffsetToMinutes($utcOffset)
        ];

        return $result;
    }

    /**
     * convert offset from `01:00:00` to `+01:00` or `-02:00:00` to `-02:00`
     */
    private function convertUtcOffset($offset)
    {
        return $offset[0] == '-' ? substr($offset, 0, 6) : '+' . substr($offset, 0, 5);
    }

    private function convertOffsetToMinutes($offset)
    {
       $sign = $offset[0];
       list($hours, $minutes) = explode(':', substr($offset, 1));
       $offsetInMinutes = $sign . (intval($hours) * 60 + intval($minutes));
       return intval($offsetInMinutes);
    }

    /**
     * @param $data
     * @param $username
     * @return mixed
     */
    public function updateProfile($data, $username)
    {
        $this->getRestClient()->post(sprintf(self::USER_URL, $username), $data);
        return true;
    }

    /**
     * @param $data
     * @param $username
     * @return mixed
     */
    public function updateTimeZone($data, $username)
    {
        $this->getRestClient()->post(self::ME_URL, $data);
        return true;
    }

    /**
     * @param $value
     * @param $username
     */
    public function setNeverAskTimeZoneChange($value, $username)
    {
        $this->db->where('username', $username)->update('users', ['never_ask_timezone_change' => $value]);
    }

    /**
     * @param $value
     * @param $username
     */
    public function setUseBrowserTime($value, $username)
    {
        $this->db->where('username', $username)->update('users', ['use_browser_time' => $value]);
    }

    /**
     * @param $username
     * @return int
     */
    public function getNeverAskTimeZoneChange($username)
    {
        $value = $this->db
            ->where('username', $username)
            ->select('never_ask_timezone_change')
            ->get('users')
            ->row_array();
        return isset($value['never_ask_timezone_change']) ? $value['never_ask_timezone_change'] : 0;
    }

    public function getCurrentTimeZone($username)
    {
        $profile = $this->getProfileData($username);
        $tz = isset($profile['time_zone']) ? $this->getTimeZone($profile['time_zone']) : null;
        return $tz;
    }

    /**
     * @param $username
     * @return int
     */
    public function getUseBrowserTime($username)
    {
        $value = $this->db
            ->where('username', $username)
            ->select('use_browser_time')
            ->get('users')
            ->row_array();
        return isset($value['use_browser_time']) ? $value['use_browser_time'] : 0;
    }

    /**
     * @param $value
     * @param $username
     */
    public function setDarkMode(int $value, string $username)
    {
        $this->db->where('username', $username)->update('users', ['dark_mode' => $value]);
    }

    public function getDarkMode($username)
    {
        $value = $this->db
            ->where('username', $username)
            ->select('dark_mode')
            ->get('users')
            ->row_array();
        return isset($value['dark_mode']) ? $value['dark_mode'] : 0;
    }

    public function getAdditionalData($username, $key)
    {
        $stmt = $this->pdo->prepare('SELECT additional_data->:key as data FROM users WHERE username = :username');
        $stmt->execute(['key' => $key, 'username' => $username]);
        return ($stmt->fetch(PDO::FETCH_ASSOC))['data'];
    }

    public function setAdditionalData($username, $key, $data)
    {
        $stmt = $this->pdo->prepare('UPDATE users SET additional_data = jsonb_set(additional_data, :key, :data) WHERE username = :username');
        $stmt->execute(['key' => '{' . $key . '}', 'data' => json_encode($data), 'username' => $username]);
    }
}
