<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Carbon\Carbon;
use Spatie\Permission\Traits\HasRoles;

use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
class User extends Authenticatable
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    use HasFactory, Notifiable;
    use HasRoles;
    use LogsActivity;


    /**
     * The attributes that are mass assignable.
     *
     * @var list<string>
     */
    protected $fillable = [
        'name',
        'qr_code',
        'email',
        'password',
        'people_id',
        'is_active',
        'couple_id',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var list<string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->useLogName('user')
            ->logOnly(['name', 'email', 'people_id', 'is_active','password'])
            ->logOnlyDirty();
    }
        // (Opcional) Personalize quais eventos logar. Padrão: created, updated, deleted
    protected static $recordEvents = ['created', 'updated', 'deleted'];

    // // (Opcional) Defina quais atributos monitorar. Padrão: todos ('*')
    protected static $logAttributes = ['name','email', 'people_id', 'is_active'];
    public function people()
    {
        return $this->belongsTo(People::class, 'people_id');
    }

    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */

    public function membership_users()
    {
        return $this->hasMany(Membership_users::class, 'user_id');
    }   
    public function entry_time_users()
    {
        return $this->hasMany(Entry_time_users::class, 'user_id');
    }
    public function assistance()
    {
        return $this->hasMany(Assistance::class, 'user_id');
    }
    public function company_user()
    {
        return $this->hasOne(Company_user::class, 'user_id');
    }

    public function couple()
    {
        return $this->belongsTo(User::class, 'couple_id');
    }

    public function coupledByUsers()
    {
        return $this->hasMany(User::class, 'couple_id');
    }

    public function hasCoupleLink(): bool
    {
        if (! empty($this->couple_id)) {
            return true;
        }

        if (array_key_exists('coupled_by_users_count', $this->attributes)) {
            return (int) $this->attributes['coupled_by_users_count'] > 0;
        }

        if ($this->relationLoaded('coupledByUsers')) {
            return $this->coupledByUsers->isNotEmpty();
        }

        return $this->coupledByUsers()->exists();
    }

    protected function resolveCurrentMembershipUser(): ?Membership_users
    {
        $now = Carbon::now();

        $membershipUsers = Membership_users::query()
            ->where('user_id', $this->id)
            ->where(function ($query) use ($now): void {
                // Preferred: membership bought in a sale detail during current month.
                $query->whereIn('id', function ($subQuery) use ($now): void {
                    $subQuery->select('sd.membership_user_id')
                        ->from('sale_details as sd')
                        ->join('sale as s', 's.id', '=', 'sd.sale_id')
                        ->whereNotNull('sd.membership_user_id')
                        ->where('s.user_id', $this->id)
                        ->whereMonth('s.created_at', $now->month)
                        ->whereYear('s.created_at', $now->year);
                })
                // Fallback: manually assigned membership without sale_id in current month.
                ->orWhere(function ($manualQuery) use ($now): void {
                    $manualQuery->whereNull('sale_id')
                        ->whereMonth('start_date', $now->month)
                        ->whereYear('start_date', $now->year);
                });
            })
            ->with('membership')
            ->orderByDesc('is_active')
            ->orderByDesc('start_date')
            ->orderByDesc('id')
            ->get();

        return $membershipUsers
            ->firstWhere('is_active', 1)
            ?? $membershipUsers->first();
    }

    public function totalDaysOfMembership(): int
    {
        $membershipUser = $this->resolveCurrentMembershipUser();

        if (! $membershipUser) {
            return 0;
        }

        if (! $membershipUser->relationLoaded('membership')) {
            $membershipUser->load('membership');
        }

        return (int) ($membershipUser->membership?->days ?? 0);
    }

    public function daysOfMembership(): int
    {
        $now = Carbon::now();
        $membershipUser = $this->resolveCurrentMembershipUser();

        if (! $membershipUser) {
            return 0;
        }

        $membershipDays = $this->totalDaysOfMembership();
        $startDate = $membershipUser->start_date ? Carbon::parse($membershipUser->start_date)->startOfDay() : null;
        $endDate = $membershipUser->end_date ? Carbon::parse($membershipUser->end_date)->endOfDay() : null;

        $assistanceQuery = $this->assistance();

        $assistanceQuery
            ->whereMonth('created_at', $now->month)
            ->whereYear('created_at', $now->year);

        if ($startDate) {
            $assistanceQuery->where('created_at', '>=', $startDate);
        }

        if ($endDate) {
            $assistanceQuery->where('created_at', '<=', $endDate);
        }

        $consumedDays = (int) $assistanceQuery
            ->selectRaw('COUNT(DISTINCT DATE(created_at)) as consumed_days')
            ->value('consumed_days');

        if ($membershipDays <= 0) {
            return max(0, $consumedDays);
        }

        return max(0, min($consumedDays, $membershipDays));
    }
    public function getPercentageAssistence(): float
    {
        $now = Carbon::now();
        $membershipUsers = $this->membership_users;

        $membershipUser = $membershipUsers
            ->first(function ($membershipUser) use ($now): bool {
                if ((int) $membershipUser->is_active !== 1) {
                    return false;
                }

                $startDate = $membershipUser->start_date ? Carbon::parse($membershipUser->start_date)->startOfDay() : null;
                $endDate = $membershipUser->end_date ? Carbon::parse($membershipUser->end_date)->endOfDay() : null;

                if ($startDate && $now->lt($startDate)) {
                    return false;
                }

                if ($endDate && $now->gt($endDate)) {
                    return false;
                }

                return true;
            })
            ?? $membershipUsers->firstWhere('is_active', 1)
            ?? $membershipUsers->first();

        if (!$membershipUser) {
            return 0.0;
        }

        if (! $membershipUser->relationLoaded('membership')) {
            $membershipUser->load('membership');
        }

        $membershipDays = (int) ($membershipUser->membership?->days ?? 0);
        $entryTimeUsersCount = $this->entry_time_users->count();
        $assistanceCount = $this->assistance->count();

        $expectedAssistance = $membershipDays > 0
            ? $membershipDays * $entryTimeUsersCount
            : 0;

        return $expectedAssistance > 0
            ? round(min(100, ($assistanceCount / $expectedAssistance) * 100), 2)
            : 0.0;
    }
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}
