<?php

namespace Ignite\Core\Entities;

use Ignite\Core\Contracts\Entities\Participant as ParticipantContract;
use Ignite\Packages\Presenter\Contracts\Presenter;
use Ignite\Packages\Presenter\Traits\Presentable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletes;
use OwenIt\Auditing\Auditable;
use OwenIt\Auditing\Contracts\Auditable as AuditableContract;

/**
 * Class Participant
 *
 * @property int $user_id
 * @property string|null $old_id
 * @property string|null $title
 * @property string $email
 * @property string $first
 * @property string $last
 * @property string|null $type
 * @property string|null $employee_id
 * @property string|null $phone1
 * @property string|null $phone2
 * @property string|null $phone3
 * @property int|null $distributor_id
 * @property string|null $department_1
 * @property string|null $department_2
 * @property string|null $address_1
 * @property string|null $address_2
 * @property string|null $address_3
 * @property string|null $city
 * @property string|null $state
 * @property string|null $postal
 * @property string|null $country
 * @property string|null $alternate_email
 * @property string|null $region
 * @property string|null $ssn
 * @property string|null $agree_confirm_1
 * @property int $status
 * @property int $archived
 * @property int $internal
 * @property string|null $internal_notes
 * @property string|null $reloadable_id
 * @property string|null $reloadable_created_at
 * @property string|null $approved_at
 * @property \Illuminate\Support\Carbon|null $deleted_at
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @property-read \Illuminate\Database\Eloquent\Collection|\Ignite\Core\Entities\Audit[] $audits
 * @property-read int|null $audits_count
 * @property-read mixed $last_login_at
 * @property-read \Illuminate\Database\Eloquent\Collection|\Ignite\Core\Entities\Note[] $notes
 * @property-read int|null $notes_count
 * @property-read \Illuminate\Database\Eloquent\Collection|\Ignite\Core\Entities\Transaction[] $transactions
 * @property-read int|null $transactions_count
 * @property-read \Ignite\Core\Entities\User $user
 * @method static Builder|Participant byEmail($email)
 * @method static Builder|Participant newModelQuery()
 * @method static Builder|Participant newQuery()
 * @method static \Illuminate\Database\Query\Builder|Participant onlyTrashed()
 * @method static Builder|Participant query()
 * @method static Builder|Participant whereAddress1($value)
 * @method static Builder|Participant whereAddress2($value)
 * @method static Builder|Participant whereAddress3($value)
 * @method static Builder|Participant whereAgreeConfirm1($value)
 * @method static Builder|Participant whereAlternateEmail($value)
 * @method static Builder|Participant whereApprovedAt($value)
 * @method static Builder|Participant whereArchived($value)
 * @method static Builder|Participant whereCity($value)
 * @method static Builder|Participant whereCountry($value)
 * @method static Builder|Participant whereCreatedAt($value)
 * @method static Builder|Participant whereDeletedAt($value)
 * @method static Builder|Participant whereDepartment1($value)
 * @method static Builder|Participant whereDepartment2($value)
 * @method static Builder|Participant whereDistributorId($value)
 * @method static Builder|Participant whereEmail($value)
 * @method static Builder|Participant whereEmployeeId($value)
 * @method static Builder|Participant whereFirst($value)
 * @method static Builder|Base whereHasPermission(string $permission, ?\Ignite\Core\Entities\User $user = null)
 * @method static Builder|Participant whereInternal($value)
 * @method static Builder|Participant whereInternalNotes($value)
 * @method static Builder|Participant whereLast($value)
 * @method static Builder|Participant whereOldId($value)
 * @method static Builder|Participant wherePhone1($value)
 * @method static Builder|Participant wherePhone2($value)
 * @method static Builder|Participant wherePhone3($value)
 * @method static Builder|Participant wherePostal($value)
 * @method static Builder|Participant whereRegion($value)
 * @method static Builder|Participant whereReloadableCreatedAt($value)
 * @method static Builder|Participant whereReloadableId($value)
 * @method static Builder|Participant whereSsn($value)
 * @method static Builder|Participant whereState($value)
 * @method static Builder|Participant whereStatus($value)
 * @method static Builder|Participant whereTitle($value)
 * @method static Builder|Participant whereType($value)
 * @method static Builder|Participant whereUpdatedAt($value)
 * @method static Builder|Participant whereUserId($value)
 * @method static \Illuminate\Database\Query\Builder|Participant withTrashed()
 * @method static \Illuminate\Database\Query\Builder|Participant withoutTrashed()
 * @mixin \Eloquent
 */
class Participant extends Base implements AuditableContract, Presenter, ParticipantContract
{
    use Auditable;
    use SoftDeletes;
    use Presentable;

    public const STATUS_INACTIVE = 0;
    public const STATUS_ACTIVE = 1;
    public const STATUS_PENDING = 2;

    public const ARCHIVED = 1;
    public const UNARCHIVED = 0;

    /**
     * The table name.
     * @var string
     */
    protected $table = 'core_participant';

    /**
     * The primary key.
     * @var string
     */
    protected $primaryKey = 'user_id';

    /**
     * Should the timestamps be audited?
     *
     * @var bool
     */
    protected $auditTimestamps = false;

    /**
     * Custom Audit Driver
     *
     * @var \Ignite\Core\Audit\ParticipantDriver
     */
    protected $auditDriver = \Ignite\Core\Audit\ParticipantDriver::class;

    /**
     * Participant presenter.
     *
     * @var string
     */
    protected $presenter = \Ignite\Core\Presenters\Participant::class;

    /**
     * Attributes to exclude from the Audit.
     *
     * @var array
     */
    protected $auditExclude = [
        'id',
        'updated_at',
        'created_at',
    ];

    /**
     * Don't auto-increment, or set Primary Key = 0
     * @var boolean
     */
    public $incrementing = false;

    /**
     * The participant status options.
     * @var array
     */
    public static $statuses = [
        self::STATUS_ACTIVE => 'active',
        self::STATUS_INACTIVE => 'inactive',
        self::STATUS_PENDING => 'pending',
    ];

    /**
     * Perform any actions required after the model boots.
     *
     * @return void
     */
    protected static function booted()
    {
        static::addGlobalScope(app(Scopes\ParticipantScope::class));
    }

    /**
     * Get a list of Participant statuses.
     *
     * @return array
     */
    public static function getStatusList()
    {
        return self::$statuses;
    }

    /**
     * Determine whether the participant is active.
     *
     * @return bool
     */
    public function isActive()
    {
        return $this->status === static::STATUS_ACTIVE;
    }

    /**
     * Determine whether the participant is inactive.
     *
     * @return bool
     */
    public function isInactive()
    {
        return $this->status === static::STATUS_INACTIVE;
    }

    /**
     * Determine whether the participant is active.
     *
     * @return bool
     */
    public function isPending()
    {
        return $this->status === static::STATUS_PENDING;
    }

    /**
     * Determine whether the participant is archived.
     *
     * @return bool
     */
    public function isArchived()
    {
        return $this->status === static::ARCHIVED;
    }

    /**
     * Determine whether the participant is unarchived.
     *
     * @return bool
     */
    public function isUnarchived()
    {
        return $this->status === static::UNARCHIVED;
    }

    /**
     * The relationship to the User model.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * The relationship to the AppNotes model.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function notes()
    {
        return $this->hasMany(Note::class, 'table_primary_id', 'user_id')
            ->whereIn('table_name', ['user', 'participant'])
            ->orderBy('created_at', 'desc');
    }

    /**
     * The relationship to transactions.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function transactions()
    {
        return $this->hasMany(Transaction::class, 'user_id', 'user_id');
    }

    /**
     * Scope a query by email.
     *
     * @param Builder $query
     * @param string $email
     */
    public function scopeByEmail(Builder $query, $email)
    {
        $query->where('email', $email);
    }

    /**
     * The participant's full name.
     *
     * @return string
     */
    public function fullName()
    {
        return "{$this->first} {$this->last}";
    }

    /**
     * We want to avoid doing : protected $appends = ['last_login_at'] to avoid loading two queries each time, instead, we only want to
     * load the User Entity on demand and avoid an overload.
     *
     * The participant's last login at appended attribute.
     *
     */
    public function getLastLoginAtAttribute()
    {
        return $this->user->last_login_at ?? null;
    }

    /**
     * Determine whether the current participant user can edit the given user's account.
     *
     * @param User $user
     *
     * @return bool
     */
    public function canEditUser(User $user)
    {
        return $this->user->can('core.user.participant.update', $user);
    }

    /**
     * The url that the logged in user can use to edit a participant account.
     *
     * @param $user
     *
     * @return string
     */
    public function getEditUserUrl($user)
    {
        return $this->canEditUser($user)
            ? route('admin.participant.edit', $user->getKey())
            : url('/participant/edit');
    }

    /**
     * The identifier for the record in the audit log.
     *
     * @return mixed
     */
    public static function getAuditFriendlyField()
    {
        return ['first', 'last'];
    }
}
