<?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 title
 * @property string email
 * @property string first
 * @property string last
 * @property string type
 * @property string employee_id
 * @property string phone1
 * @property string phone2
 * @property string phone3
 * @property string company
 * @property string department_1
 * @property string department_2
 * @property string address_1
 * @property string address_2
 * @property string city
 * @property string state
 * @property string postal
 * @property string country
 * @property string alternate_email
 * @property string region
 * @property string dob
 * @property string ssn
 * @property string agree_confirm_1
 * @property string agree_confirm_2
 * @property string status
 * @property string archived
 * @property string idc
 * @property int internal
 * @property string internal_notes
 * @property string approved_at
 * @property string deleted_at
 * @property string created_at
 * @property string updated_at
 * @property User user
 */
class Participant extends Base implements AuditableContract, Presenter, ParticipantContract
{
    use Auditable, SoftDeletes, Presentable;

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

    const ARCHIVED = 1;
    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'];
    }
}
