<?php

namespace App\Models;

use App\Models\Traits\HasAuditFields;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * Employee Salary Structure Model
 *
 * Defines the salary components and deduction percentages for each employee.
 * Used as the basis for monthly payroll calculations.
 */
class EmployeeSalaryStructure extends Model
{
    use HasFactory, SoftDeletes, HasAuditFields;

    protected $table = 'employee_salary_structures';

    /**
     * Status constants
     */
    public const STATUS_ACTIVE = 'active';
    public const STATUS_INACTIVE = 'inactive';

    protected $fillable = [
        'employee_id',
        'basic_da',
        'hra',
        'conveyance',
        'washing_allowance',
        'incentive_per_hour',
        'fixed_salary',
        'pf_percentage',
        'esi_percentage',
        'pt_percentage',
        'status',
        'effective_from',
        'effective_to',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'basic_da' => 'decimal:2',
        'hra' => 'decimal:2',
        'conveyance' => 'decimal:2',
        'washing_allowance' => 'decimal:2',
        'incentive_per_hour' => 'decimal:2',
        'fixed_salary' => 'decimal:2',
        'pf_percentage' => 'decimal:2',
        'esi_percentage' => 'decimal:2',
        'pt_percentage' => 'decimal:2',
        'effective_from' => 'date',
        'effective_to' => 'date',
    ];

    // =========================================================================
    // RELATIONSHIPS
    // =========================================================================

    public function employee()
    {
        return $this->belongsTo(EmployeeDetails::class, 'employee_id');
    }

    // =========================================================================
    // SCOPES
    // =========================================================================

    /**
     * Scope to filter by employee
     */
    public function scopeForEmployee(Builder $query, int $employeeId): Builder
    {
        return $query->where('employee_id', $employeeId);
    }

    /**
     * Scope to filter active structures
     */
    public function scopeActive(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_ACTIVE);
    }

    /**
     * Scope to filter inactive structures
     */
    public function scopeInactive(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_INACTIVE);
    }

    /**
     * Scope to get current effective structure
     */
    public function scopeCurrentlyEffective(Builder $query): Builder
    {
        $today = now()->toDateString();
        return $query->where('status', self::STATUS_ACTIVE)
            ->where(function ($q) use ($today) {
                $q->whereNull('effective_from')
                  ->orWhere('effective_from', '<=', $today);
            })
            ->where(function ($q) use ($today) {
                $q->whereNull('effective_to')
                  ->orWhere('effective_to', '>=', $today);
            });
    }

    // =========================================================================
    // HELPER METHODS
    // =========================================================================

    /**
     * Get all valid statuses
     */
    public static function getStatuses(): array
    {
        return [
            self::STATUS_ACTIVE,
            self::STATUS_INACTIVE,
        ];
    }

    /**
     * Check if active
     */
    public function isActive(): bool
    {
        return $this->status === self::STATUS_ACTIVE;
    }

    /**
     * Calculate gross salary (sum of all components)
     */
    public function calculateGrossSalary(): float
    {
        return $this->basic_da
             + $this->hra
             + $this->conveyance
             + $this->washing_allowance;
    }

    /**
     * Calculate PF amount based on percentage
     */
    public function calculatePF(?float $gross = null): float
    {
        $gross = $gross ?? $this->calculateGrossSalary();
        return round(($gross * $this->pf_percentage) / 100, 2);
    }

    /**
     * Calculate ESI amount based on percentage
     */
    public function calculateESI(?float $gross = null): float
    {
        $gross = $gross ?? $this->calculateGrossSalary();
        return round(($gross * $this->esi_percentage) / 100, 2);
    }

    /**
     * Calculate PT amount based on percentage
     */
    public function calculatePT(?float $gross = null): float
    {
        $gross = $gross ?? $this->calculateGrossSalary();
        return round(($gross * $this->pt_percentage) / 100, 2);
    }

    /**
     * Calculate total deductions
     */
    public function calculateTotalDeductions(?float $gross = null): float
    {
        $gross = $gross ?? $this->calculateGrossSalary();
        return $this->calculatePF($gross)
             + $this->calculateESI($gross)
             + $this->calculatePT($gross);
    }

    /**
     * Calculate net salary (gross - deductions)
     */
    public function calculateNetSalary(): float
    {
        $gross = $this->calculateGrossSalary();
        return $gross - $this->calculateTotalDeductions($gross);
    }

    /**
     * Get incentive amount for given hours
     */
    public function calculateIncentive(float $hours): float
    {
        return round($hours * $this->incentive_per_hour, 2);
    }

    /**
     * Get salary breakdown as array
     */
    public function getSalaryBreakdown(): array
    {
        $gross = $this->calculateGrossSalary();

        return [
            'earnings' => [
                'basic_da' => $this->basic_da,
                'hra' => $this->hra,
                'conveyance' => $this->conveyance,
                'washing_allowance' => $this->washing_allowance,
                'gross' => $gross,
            ],
            'deductions' => [
                'pf' => $this->calculatePF($gross),
                'esi' => $this->calculateESI($gross),
                'pt' => $this->calculatePT($gross),
                'total' => $this->calculateTotalDeductions($gross),
            ],
            'net_salary' => $this->calculateNetSalary(),
            'fixed_salary' => $this->fixed_salary,
        ];
    }
}
