<?php

namespace App\Models;

use App\Enums\FeatureEnum;
use App\Notifications\ResetUserPassword;
use App\Notifications\VerifyCodeUserEmail;
// use App\Notifications\VerifyUserEmail;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\DB;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, CanResetPassword;

    const STATUS_PENDING_EMAIL_CONFIRMATION = 'pendingEmailConfirmation';
    const STATUS_ACTIVE = 'active';
    const STATUS_INACTIVE = 'inactive';
    const AVAILABLE_STATUS = [
        self::STATUS_PENDING_EMAIL_CONFIRMATION,
        self::STATUS_ACTIVE,
        self::STATUS_INACTIVE,
    ];

    const REGISTRATION_STEP_EMAIL_VERIFICATION = 'email_verification';
    const REGISTRATION_STEP_NAME_SETUP = 'name_setup';
    const REGISTRATION_STEP_ACCOUNT_SETUP = 'account_setup';
    const REGISTRATION_STEP_BILLING_SETUP = 'billing_setup';
    const REGISTRATION_STEP_PROFILE_SETUP = 'profile_setup';
    const REGISTRATION_STEP_COMPLETED = 'completed';

    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
        'validation_code_expires_at' => 'datetime',
    ];

    public function sendPasswordUserResetNotification($token, $email)
    {
        $this->notify(new ResetUserPassword($token, $email));
    }

    // public function sendEmailVerificationNotification()
    // {
    //     $this->notify(new VerifyUserEmail);
    // }

    public function sendEmailCodeVerificationNotification()
    {
        $this->notify(new VerifyCodeUserEmail);
    }

    public function ownAccount()
    {
        return $this->hasOne(Account::class, 'owner_id');
    }

    public function accountMember()
    {
        return $this->hasOne(AccountMember::class);
    }

    public function profileRole()
    {
        return $this->belongsTo(UserProfileRole::class, 'user_profile_role_id');
    }

    public function profileSpecialisation()
    {
        return $this->belongsTo(UserProfileSpecialisation::class, 'user_profile_specialisation_id');
    }

    public function watchlists()
    {
        return $this->hasMany(Watchlist::class);
    }

    public function cvEntries()
    {
        return $this->hasMany(CvEntry::class);
    }

    public function hasFeature(FeatureEnum $feature, $needAdmin = false, $notWhileTrial = false)
    {
        // This is done like this to minimize the number of queries
        return DB::Table('account_members')
            ->join('accounts', 'account_members.account_id', '=', 'accounts.id')
            ->join('subscriptions', 'accounts.id', '=', 'subscriptions.account_id')
            ->join('subscription_plans', 'subscriptions.subscription_plan_id', '=', 'subscription_plans.id')
            ->join('subscription_plan_features', 'subscription_plans.id', '=', 'subscription_plan_features.subscription_plan_id')
            ->join('features', 'subscription_plan_features.feature_id', '=', 'features.id')
            ->where('account_members.user_id', $this->id)
            ->where('account_members.status', AccountMember::STATUS_ACCEPTED)
            ->where('subscriptions.status', Subscription::STATUS_ACTIVE)
            ->where('features.name', $feature)
            ->when($needAdmin, function ($query) {
                return $query->where('account_members.is_admin', true);
            })
            ->when($notWhileTrial, function ($query) {
                return $query->where('subscriptions.is_trial', false);
            })
            ->exists();
    }

    public function SearchProfiles(): HasMany
    {
        return $this->hasMany(SearchProfile::class);
    }

    public function isBasicUser(): bool
    {
        $member = $this->accountMember;
        $account = $member ? $member->account : null;
        $activeSubscription = $account ? $account->activeSubscriptions->first() : null;

        return empty($account) || empty($activeSubscription) || $activeSubscription->status !== Subscription::STATUS_ACTIVE;
    }
}
