<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    /** @use HasFactory<UserFactory> */
    use HasApiTokens, HasFactory, HasRoles, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'account_id',
        'shift_id',
        'name',
        'email',
        'country_code',
        'phone',
        'designation',
        'fcm_token',
        'image',
        'image_path',
        'otp',
        'otp_expires_at',
        'status',
        'is_deleted',
    ];

    // In User.php

    public function subordinates(): BelongsToMany
    {
        // The users that are tagged under this user
        return $this->belongsToMany(User::class, 'user_mappings', 'parent_user_id', 'child_user_id');
    }

    public function supervisors(): BelongsToMany
    {
        // The users that this user is tagged under
        return $this->belongsToMany(User::class, 'user_mappings', 'child_user_id', 'parent_user_id');
    }

    public function account(): BelongsTo
    {
        return $this->belongsTo(Account::class);
    }

    public function user_profile(): HasOne
    {
        return $this->hasOne(UserProfile::class);
    }

    public function user_address(): HasOne
    {
        return $this->hasOne(UserAddress::class);
    }

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

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

    public function shift(): BelongsTo
    {
        return $this->belongsTo(Shift::class);
    }

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

    public function current_leave_entitlements(): HasMany
    {
        $today = now()->toDateString();

        return $this->hasMany(LeaveEntitlement::class)
            ->where('start_date', '<=', $today)
            ->where('end_date', '>=', $today);
    }

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

    public function current_leave_applications(): HasMany
    {
        $fiscal = $this->getFiscalBoundaries();

        return $this->hasMany(LeaveApplication::class)
            ->where(function ($query) use ($fiscal) {
                $query->whereBetween('start_date', [$fiscal['start'], $fiscal['end']])
                    ->orWhereBetween('end_date', [$fiscal['start'], $fiscal['end']])
                    ->orWhere(function ($sub) use ($fiscal) {
                        $sub->where('start_date', '<', $fiscal['start'])
                            ->where('end_date', '>', $fiscal['end']);
                    });
            })
            ->orderBy('start_date', 'desc');
    }

    private function getFiscalBoundaries(): array
    {
        $now = now();
        $startYear = ($now->month < 4) ? $now->year - 1 : $now->year;

        return [
            'start' => "{$startYear}-04-01",
            'end' => ($startYear + 1).'-03-31',
        ];
    }

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

    public function leave_approvals(): HasMany
    {
        return $this->hasMany(LeaveApproval::class, 'approver_id');
    }

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

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

    public function asset_creators(): HasMany
    {
        return $this->hasMany(UserAsset::class, 'creator_id');
    }

    public function active_sale_target(): HasOne
    {
        return $this->hasOne(SaleTarget::class)->where('is_active', true);
    }

    public function meeting_assign_users(): User|HasMany
    {
        return $this->hasMany(MeetingUser::class);
    }

    public function meeting_creator(): BelongsTo
    {
        return $this->belongsTo(Meeting::class, 'created_by');
    }

    public function quotation(): User|HasMany
    {
        return $this->hasMany(Quotation::class, 'created_by');
    }

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

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

    public function todayAttendance(): HasOne
    {
        return $this->hasOne(Attendance::class)
            ->where('attendance_date', now()->toDateString());
    }

    public function attendanceForDate($date): HasOne
    {
        return $this->hasOne(Attendance::class)
            ->where('attendance_date', $date);
    }

    public function project_team_lead(): User|HasMany
    {
        return $this->hasMany(Project::class, 'team_leader');
    }
}
