<?php

namespace App\Models;

use Illuminate\Support\Carbon;
use Illuminate\Database\Eloquent\Model;

class Employee extends Model
{
    public const DEFAULT_SALARY_WORKING_DAYS_DIVISOR = 26;

    protected $fillable = [
        'user_id',
        'full_name',
        'address',
        'phone',
        'avatar_path',
        'is_active',
        'activated_at',
        'deactivated_at',
        'job_title',
        'attendance_time',
        'departure_time',
        'allow_outside_company',
        'allow_grace_period',
        'grace_minutes',
        'is_programmer',
        'programmer_work_hours',
        'notes',
        'base_salary',
        'role_id',
        'general_percentage',
        'role_percentage',
    ];

    protected $casts = [
        'user_id' => 'int',
        'base_salary' => 'int',
        'general_percentage' => 'int',
        'role_percentage' => 'int',
        'role_id' => 'int',
        'allow_outside_company' => 'bool',
        'allow_grace_period' => 'bool',
        'grace_minutes' => 'int',
        'is_programmer' => 'bool',
        'programmer_work_hours' => 'int',
        'is_active' => 'bool',
        'activated_at' => 'datetime',
        'deactivated_at' => 'datetime',
    ];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function role()
    {
        return $this->belongsTo(Role::class);
    }

    public function serviceCommissions()
    {
        return $this->hasMany(EmployeeServiceCommission::class);
    }

    public function commissions()
    {
        return $this->hasMany(EmployeeCommission::class);
    }

    public function penalties()
    {
        return $this->hasMany(EmployeePenalty::class);
    }

    public function bonuses()
    {
        return $this->hasMany(EmployeeBonus::class);
    }

    public function withdrawals()
    {
        return $this->hasMany(EmployeeWithdrawal::class);
    }

    public function getAvatarUrlAttribute(): ?string
    {
        if (! $this->avatar_path) {
            return null;
        }

        return '/storage/'.ltrim($this->avatar_path, '/');
    }

    public function dailyRate(int $workingDaysDivisor = self::DEFAULT_SALARY_WORKING_DAYS_DIVISOR): float
    {
        $baseSalary = (int) ($this->base_salary ?? 0);
        $workingDaysDivisor = max(1, (int) $workingDaysDivisor);

        return $baseSalary > 0 ? ($baseSalary / $workingDaysDivisor) : 0.0;
    }

    public function scheduledWorkMinutesPerDay(string $tz = 'Asia/Baghdad'): int
    {
        $startRaw = is_string($this->attendance_time) ? trim($this->attendance_time) : '';
        $endRaw = is_string($this->departure_time) ? trim($this->departure_time) : '';

        if ($startRaw === '' || $endRaw === '') {
            return 0;
        }

        $startRaw = preg_match('/^\d{2}:\d{2}$/', $startRaw) ? $startRaw.':00' : $startRaw;
        $endRaw = preg_match('/^\d{2}:\d{2}$/', $endRaw) ? $endRaw.':00' : $endRaw;

        try {
            $start = Carbon::createFromFormat('Y-m-d H:i:s', '2000-01-01 '.$startRaw, $tz);
            $end = Carbon::createFromFormat('Y-m-d H:i:s', '2000-01-01 '.$endRaw, $tz);
        } catch (\Throwable $e) {
            return 0;
        }

        if ($end->lessThanOrEqualTo($start)) {
            $end->addDay();
        }

        return (int) $start->diffInMinutes($end);
    }

    public function minuteRate(int $workingDaysDivisor = self::DEFAULT_SALARY_WORKING_DAYS_DIVISOR, string $tz = 'Asia/Baghdad'): float
    {
        $dailyRate = $this->dailyRate($workingDaysDivisor);
        $minutes = $this->scheduledWorkMinutesPerDay($tz);

        if ($dailyRate <= 0 || $minutes <= 0) {
            return 0.0;
        }

        return $dailyRate / $minutes;
    }
}
