<?php

namespace App\Models;

use App\Models\Traits\HasAuditFields;
use App\Models\Traits\HasScopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;

/**
 * Employee Salary Detail Model
 *
 * Stores monthly salary calculations with approval workflow.
 * Contains computed salary components, deductions, and final net salary.
 */
class EmployeeSalaryDetail extends Model
{
    use HasFactory, SoftDeletes, HasAuditFields, HasScopes;

    protected $table = 'employee_salary_details';

    /**
     * Approval status constants
     */
    public const STATUS_PENDING = 'pending';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_REJECTED = 'rejected';

    /**
     * Payment mode constants
     */
    public const PAYMENT_BANK = 'bank';
    public const PAYMENT_CASH = 'cash';
    public const PAYMENT_CHEQUE = 'cheque';
    public const PAYMENT_UPI = 'upi';

    protected $fillable = [
        'employee_id',
        'month_year',
        'basic_da',
        'hra',
        'conveyance',
        'washing_allowance',
        'fixed_salary',
        'no_of_days_worked',
        'leave_given',
        'sundays_count',
        'holidays_count',
        'total_days_for_salary',
        'drawn_salary',
        'incentive_hrs',
        'sunday_ot_hours',
        'holiday_ot_hours',
        'incentive_rate',
        'incentive_amount',
        'attendance_bonus',
        'gross_salary',
        'esi',
        'pf',
        'pt',
        'advance_deduction',
        'net_salary',
        'payment_mode',
        'approval_status',
        'approved_by',
        'approved_at',
        'rejection_reason',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'month_year' => 'date:Y-m',
        'approved_at' => 'datetime',
        'basic_da' => 'decimal:2',
        'hra' => 'decimal:2',
        'conveyance' => 'decimal:2',
        'washing_allowance' => 'decimal:2',
        'fixed_salary' => 'decimal:2',
        'no_of_days_worked' => 'decimal:2',
        'leave_given' => 'decimal:2',
        'total_days_for_salary' => 'decimal:2',
        'drawn_salary' => 'decimal:2',
        'incentive_hrs' => 'decimal:2',
        'sunday_ot_hours' => 'decimal:2',
        'holiday_ot_hours' => 'decimal:2',
        'incentive_rate' => 'decimal:2',
        'incentive_amount' => 'decimal:2',
        'attendance_bonus' => 'decimal:2',
        'gross_salary' => 'decimal:2',
        'esi' => 'decimal:2',
        'pf' => 'decimal:2',
        'pt' => 'decimal:2',
        'advance_deduction' => 'decimal:2',
        'net_salary' => 'decimal:2',
    ];

    /**
     * Column configuration for HasScopes trait
     */
    protected string $dateColumn = 'month_year';
    protected string $statusColumn = 'approval_status';

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

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

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

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

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

    /**
     * Scope to filter pending records
     */
    public function scopePendingApproval(Builder $query): Builder
    {
        return $query->where('approval_status', self::STATUS_PENDING);
    }

    /**
     * Scope to filter approved records
     */
    public function scopeApprovedOnly(Builder $query): Builder
    {
        return $query->where('approval_status', self::STATUS_APPROVED);
    }

    /**
     * Scope to filter rejected records
     */
    public function scopeRejectedOnly(Builder $query): Builder
    {
        return $query->where('approval_status', self::STATUS_REJECTED);
    }

    /**
     * Scope to filter by month/year
     */
    public function scopeForMonthYear(Builder $query, string $monthYear): Builder
    {
        return $query->where('month_year', $monthYear);
    }

    /**
     * Scope to filter by payment mode
     */
    public function scopeByPaymentMode(Builder $query, string $mode): Builder
    {
        return $query->where('payment_mode', $mode);
    }

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

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

    /**
     * Get all valid payment modes
     */
    public static function getPaymentModes(): array
    {
        return [
            self::PAYMENT_BANK,
            self::PAYMENT_CASH,
            self::PAYMENT_CHEQUE,
            self::PAYMENT_UPI,
        ];
    }

    /**
     * Check if pending
     */
    public function isPending(): bool
    {
        return $this->approval_status === self::STATUS_PENDING;
    }

    /**
     * Check if approved
     */
    public function isApproved(): bool
    {
        return $this->approval_status === self::STATUS_APPROVED;
    }

    /**
     * Check if rejected
     */
    public function isRejected(): bool
    {
        return $this->approval_status === self::STATUS_REJECTED;
    }

    /**
     * Approve this salary record
     */
    public function approve(): bool
    {
        return $this->update([
            'approval_status' => self::STATUS_APPROVED,
            'approved_by' => Auth::id(),
            'approved_at' => now(),
        ]);
    }

    /**
     * Reject this salary record
     */
    public function reject(?string $reason = null): bool
    {
        return $this->update([
            'approval_status' => self::STATUS_REJECTED,
            'approved_by' => Auth::id(),
            'approved_at' => now(),
            'rejection_reason' => $reason,
        ]);
    }

    /**
     * Get total earnings
     */
    public function getTotalEarningsAttribute(): float
    {
        return $this->drawn_salary
             + $this->incentive_amount
             + $this->attendance_bonus;
    }

    /**
     * Get total deductions
     */
    public function getTotalDeductionsAttribute(): float
    {
        return $this->esi
             + $this->pf
             + $this->pt
             + $this->advance_deduction;
    }

    /**
     * Get total OT hours
     */
    public function getTotalOtHoursAttribute(): float
    {
        return $this->incentive_hrs
             + $this->sunday_ot_hours
             + $this->holiday_ot_hours;
    }

    /**
     * Get salary breakdown for payslip
     */
    public function getSalaryBreakdown(): array
    {
        return [
            'employee' => [
                'id' => $this->employee_id,
                'name' => $this->employee?->name,
            ],
            'period' => $this->month_year?->format('F Y'),
            'earnings' => [
                'basic_da' => $this->basic_da,
                'hra' => $this->hra,
                'conveyance' => $this->conveyance,
                'washing_allowance' => $this->washing_allowance,
                'drawn_salary' => $this->drawn_salary,
                'incentive_amount' => $this->incentive_amount,
                'attendance_bonus' => $this->attendance_bonus,
                'gross' => $this->gross_salary,
            ],
            'deductions' => [
                'pf' => $this->pf,
                'esi' => $this->esi,
                'pt' => $this->pt,
                'advance' => $this->advance_deduction,
                'total' => $this->total_deductions,
            ],
            'attendance' => [
                'days_worked' => $this->no_of_days_worked,
                'leave_given' => $this->leave_given,
                'sundays' => $this->sundays_count,
                'holidays' => $this->holidays_count,
                'total_days' => $this->total_days_for_salary,
            ],
            'overtime' => [
                'incentive_hrs' => $this->incentive_hrs,
                'sunday_ot' => $this->sunday_ot_hours,
                'holiday_ot' => $this->holiday_ot_hours,
                'rate' => $this->incentive_rate,
            ],
            'net_salary' => $this->net_salary,
            'payment_mode' => $this->payment_mode,
            'status' => $this->approval_status,
        ];
    }
}
