<?php

/*
 * This file is part of the AuthStack project.
 *
 * (c) Buckhill Ltd <development@buckhill.co.uk>
 *
 * This source file is subject to the Buckhill license that is bundled
 * with this source code in the file LICENSE.
 */

namespace AuthStack\Driver\Model;

use Illuminate\Database\Eloquent\Model;
use AuthStack\Driver\Errors\InvalidUserAttributesError;
use Illuminate\Database\Eloquent\ModelNotFoundException;

class User extends Model
{
    protected $table = 'users';
    protected $fillable = ['conn_id', 'unique_id', 'username', 'password', 'config', 'created_at', 'updated_at'];
    public $timestamps = true;

    protected $casts = [
        'config' => 'array',
    ];

    /**
     * @param $value
     */
    public function setConfigAttribute($value)
    {
        $this->attributes['config'] = json_encode($value, JSON_UNESCAPED_SLASHES);
    }

    /**
     * @param array $config
     *
     * @return $this
     */
    public function updateUserConfig(array $config)
    {
        $cfg = $this->getAttribute('config');

        if (!is_array($cfg)) {
            $cfg = [];
        }

        $cfg = array_merge($cfg, $config);

        $this->attributes['config'] = json_encode($cfg);

        return $this;
    }

    /**
     * @param array $attributes
     *
     * @return mixed
     *
     * @throws InvalidUserAttributesError
     */
    public static function retrieve(array $attributes)
    {
        static::checkAttributes($attributes);

        $attributes = array_merge($attributes, [
                'unique_id' => sha1(sprintf('%d.%s',
                        $attributes['conn_id'],
                        $attributes['username'])
                , true),
            ]
        );

        try {
            $model = static::where('unique_id', $attributes['unique_id'])->firstOrFail();
        } catch (ModelNotFoundException $e) {
            // No such record
            $model = static::create($attributes);
        } catch (\PDOException $e) {
            $model = static::where('unique_id', $attributes['unique_id'])->firstOrFail();
        }

        return $model;
    }

    /**
     * @param array $attributes
     *
     * @throws InvalidUserAttributesError
     */
    protected static function checkAttributes(array $attributes)
    {
        $required = ['conn_id', 'username'];

        foreach ($required as $key) {
            if (!isset($attributes[$key])) {
                throw new InvalidUserAttributesError(sprintf('Required key %s not specified in the attributes array', $key));
            }
        }
    }
}
