<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Filament\Models\Contracts\FilamentUser;
use Filament\Panel;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable implements FilamentUser
{
    /** @use HasFactory<UserFactory> */
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'google_id',
        'name',
        'username',
        'email',
        'email_verified_at',
        'password',
        'password_set_at',
        'must_change_password',
        'avatar_url',
        'role',
        'questionnaire_completed_at',
        'access_unlocked_at',
        'resume_uploaded_at',
        'resume_analyzed_at',
        'profile_completed_at',
        'last_login_at',
    ];

    /**
     * @return HasOne<QuestionnaireResponse, $this>
     */
    public function questionnaireResponse(): HasOne
    {
        return $this->hasOne(QuestionnaireResponse::class);
    }

    /**
     * @return HasOne<ResumeReport, $this>
     */
    public function resumeReport(): HasOne
    {
        return $this->hasOne(ResumeReport::class)
            ->where('is_current', true)
            ->latestOfMany();
    }

    /**
     * @return HasMany<ResumeReport, $this>
     */
    public function resumeReports(): HasMany
    {
        return $this->hasMany(ResumeReport::class);
    }

    /**
     * @return HasOne<Profile, $this>
     */
    public function profile(): HasOne
    {
        return $this->hasOne(Profile::class);
    }

    /**
     * @return HasMany<Payment, $this>
     */
    public function payments(): HasMany
    {
        return $this->hasMany(Payment::class);
    }

    /**
     * @return HasMany<SavedJob, $this>
     */
    public function savedJobs(): HasMany
    {
        return $this->hasMany(SavedJob::class);
    }

    /**
     * @return HasMany<Application, $this>
     */
    public function applications(): HasMany
    {
        return $this->hasMany(Application::class);
    }

    /**
     * @return HasMany<JobInterest, $this>
     */
    public function jobInterests(): HasMany
    {
        return $this->hasMany(JobInterest::class);
    }

    /**
     * @return HasOne<JobAlertPreference, $this>
     */
    public function jobAlertPreference(): HasOne
    {
        return $this->hasOne(JobAlertPreference::class);
    }

    /**
     * @return HasMany<JobAlertEmailLog, $this>
     */
    public function jobAlertEmailLogs(): HasMany
    {
        return $this->hasMany(JobAlertEmailLog::class);
    }

    /**
     * @return HasMany<EmailDeliveryLog, $this>
     */
    public function emailDeliveryLogs(): HasMany
    {
        return $this->hasMany(EmailDeliveryLog::class);
    }

    /**
     * @return HasMany<UserEngagementEvent, $this>
     */
    public function engagementEvents(): HasMany
    {
        return $this->hasMany(UserEngagementEvent::class);
    }

    /**
     * @return HasMany<JobAiAssistance, $this>
     */
    public function jobAiAssistances(): HasMany
    {
        return $this->hasMany(JobAiAssistance::class);
    }

    /**
     * @return HasMany<JobNote, $this>
     */
    public function jobNotes(): HasMany
    {
        return $this->hasMany(JobNote::class);
    }

    /**
     * @return HasMany<ApplicationFollowUpReminder, $this>
     */
    public function applicationFollowUpReminders(): HasMany
    {
        return $this->hasMany(ApplicationFollowUpReminder::class);
    }

    public function isAdmin(): bool
    {
        return $this->role === 'admin';
    }

    public function canAccessPanel(Panel $panel): bool
    {
        return $panel->getId() === 'admin' && $this->isAdmin();
    }

    public function hasCompletedQuestionnaire(): bool
    {
        return $this->questionnaire_completed_at !== null;
    }

    public function hasUnlockedAccess(): bool
    {
        return $this->access_unlocked_at !== null;
    }

    public function hasUploadedResume(): bool
    {
        return $this->resume_uploaded_at !== null;
    }

    public function hasAnalyzedResume(): bool
    {
        return $this->resume_analyzed_at !== null;
    }

    public function hasCompletedProfile(): bool
    {
        return $this->profile_completed_at !== null;
    }

    public function canViewMatchedJobs(): bool
    {
        return $this->hasCompletedQuestionnaire()
            && $this->hasUnlockedAccess()
            && $this->hasAnalyzedResume()
            && $this->hasCompletedProfile();
    }

    public function canApplyToJobs(): bool
    {
        return $this->canViewMatchedJobs();
    }

    public function recordJobInterest(ImportedJob $job, string $source): JobInterest
    {
        $now = now();

        $interest = $this->jobInterests()->firstOrCreate(
            [
                'imported_job_id' => $job->id,
                'source' => $source,
            ],
            [
                'view_count' => 0,
                'first_seen_at' => $now,
            ]
        );

        $interest->forceFill([
            'view_count' => ((int) $interest->view_count) + 1,
            'last_seen_at' => $now,
        ])->save();

        return $interest;
    }

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
            'password_set_at' => 'datetime',
            'must_change_password' => 'boolean',
            'questionnaire_completed_at' => 'datetime',
            'access_unlocked_at' => 'datetime',
            'resume_uploaded_at' => 'datetime',
            'resume_analyzed_at' => 'datetime',
            'profile_completed_at' => 'datetime',
            'last_login_at' => 'datetime',
        ];
    }
}
