<?php

namespace Mtc\Modules\Members\Models;

use App\Casts\OptionalEncrypted;
use App\Src\Encryption;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Validator;
use Mtc\Core\Concerns\HasDefaultAddressFields;
use Mtc\Modules\Members\Classes\BelongsToMember;

/**
 * Members Address Eloquent Model.
 *
 * @author Aleksey Lavrinenko
 * @version 06.09.2016.
 *
 * @property $type
 * @property $title
 * @property $firstname
 * @property $lastname
 * @property $address1
 * @property $address2
 * @property $city
 * @property $state
 * @property $postcode
 *
 * @property Carbon $created_at
 * @property Carbon $updated_at
 */
class MembersAddress extends Model
{
    use BelongsToMember;

    use HasFactory;

    use HasDefaultAddressFields;

    protected $table = 'members_addresses';

    protected $fillable = [
        'type',
        'title',
        'firstname',
        'middle_name',
        'lastname',
        'address1',
        'address2',
        'city',
        'state',
        'country',
        'postcode',
    ];

    const TYPE_BILLING = 'billing';
    const TYPE_SHIPPING = 'shipping';


    private $rules = [
        'address1' => 'required',
        'city' => 'required',
        'postcode' => 'required',
    ];

    protected $casts = [
        'firstname' => OptionalEncrypted::class,
        'middle_name' => OptionalEncrypted::class,
        'lastname' => OptionalEncrypted::class,
        'address1' => OptionalEncrypted::class,
        'address2' => OptionalEncrypted::class,
        'city' => OptionalEncrypted::class,
        'postcode' => OptionalEncrypted::class,
    ];

    public static $searchable = [
        'firstname',
        'lastname',
        'postcode',
    ];

    protected static function boot() : void
    {
        parent::boot();

        self::saving(function (self $model) {
            // `title` and `state` are NOT NULL with no default, but the register and
            // checkout forms don't always supply them and Laravel's
            // ConvertEmptyStringsToNull middleware turns blanks into null. Store an
            // empty string to match existing data and the equally NOT NULL
            // basket_address columns the member address is later copied into.
            foreach (['title', 'state'] as $column) {
                if ($model->{$column} === null) {
                    $model->{$column} = '';
                }
            }
        });

        self::saved(function (self $model) {
            Encryption::updateHashes($model);
        });
    }

    public function validate()
    {
        return Validator::make($this->attributes, $this->rules);
    }


    // SCOPES

    /**
     * scope billing(). Filters billing addresses
     * @param $query
     * @return Builder
     */
    public function scopeBilling($query)
    {
        return $query->where('type', 'billing');
    }

    /**
     * scope shipping. Filters shipping addresses
     * @param $query
     * @return Builder
     */
    public function scopeShipping($query)
    {
        return $query->where('type', 'shipping');
    }


    public function save_from_input(array $data)
    {
        $errors = [];

        $this->fill($data);

        $errors_bag = $this->validate()->errors();
        if ($errors_bag->isEmpty()) {
            $this->save();
        }

        $errors = \App\FlashMessage::getImplodedMessages($errors_bag);

        return $errors;
    }

    public static function newFactory()
    {
        return \Database\Factories\MemberAddressFactory::class::new();
    }
}
