<?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 Payroll Model
 *
 * Represents processed payroll records for employees.
 * Contains finalized salary calculations for a specific month.
 */
class EmployeePayroll extends Model
{
    use HasFactory, SoftDeletes, HasAuditFields, HasScopes;

    protected $table = 'employee_payrolls';

    /**
     * Status constants
     */
    public const STATUS_DRAFT = 'draft';
    public const STATUS_PENDING = 'pending';
    public const STATUS_APPROVED = 'approved';
    public const STATUS_PAID = 'paid';
    public const STATUS_REJECTED = 'rejected';

    /**
     * Payment mode constants
     */
    public const PAY_MODE_BANK = 'bank';
    public const PAY_MODE_CASH = 'cash';
    public const PAY_MODE_CHEQUE = 'cheque';
    public const PAY_MODE_UPI = 'upi';

    protected $fillable = [
        'employee_id',
        'employee_name',
        'month_year',
        'basic_da',
        'hra',
        'conveyance',
        'washing_allowance',
        'fixed_salary',
        'days_worked',
        'leave_given',
        'total_days',
        'drawn_salary',
        'incentive_hrs',
        'incentive_rate',
        'incentive_amount',
        'attendance_bonus',
        'gross_salary',
        'esi',
        'pf',
        'pt',
        'advance_deduction',
        'net_salary',
        'pay_mode',
        'status',
        'approved_by',
        'approved_at',
        'paid_at',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'month_year' => 'date:Y-m',
        'approved_at' => 'datetime',
        'paid_at' => 'datetime',
        'basic_da' => 'decimal:2',
        'hra' => 'decimal:2',
        'conveyance' => 'decimal:2',
        'washing_allowance' => 'decimal:2',
        'fixed_salary' => 'decimal:2',
        'days_worked' => 'decimal:2',
        'leave_given' => 'decimal:2',
        'total_days' => 'decimal:2',
        'drawn_salary' => 'decimal:2',
        'incentive_hrs' => '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 = '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 by month/year
     */
    public function scopeForMonthYear(Builder $query, string $monthYear): Builder
    {
        return $query->where('month_year', $monthYear);
    }

    /**
     * Scope to filter draft records
     */
    public function scopeDraft(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_DRAFT);
    }

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

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

    /**
     * Scope to filter paid records
     */
    public function scopePaid(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_PAID);
    }

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

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

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

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

    /**
     * Get all valid payment modes
     */
    public static function getPayModes(): array
    {
        return [
            self::PAY_MODE_BANK,
            self::PAY_MODE_CASH,
            self::PAY_MODE_CHEQUE,
            self::PAY_MODE_UPI,
        ];
    }

    /**
     * Check if draft
     */
    public function isDraft(): bool
    {
        return $this->status === self::STATUS_DRAFT;
    }

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

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

    /**
     * Check if paid
     */
    public function isPaid(): bool
    {
        return $this->status === self::STATUS_PAID;
    }

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

    /**
     * Submit for approval
     */
    public function submitForApproval(): bool
    {
        if (!$this->isDraft()) {
            return false;
        }
        return $this->update(['status' => self::STATUS_PENDING]);
    }

    /**
     * Approve this payroll
     */
    public function approve(): bool
    {
        if (!$this->isPending()) {
            return false;
        }
        return $this->update([
            'status' => self::STATUS_APPROVED,
            'approved_by' => Auth::id(),
            'approved_at' => now(),
        ]);
    }

    /**
     * Reject this payroll
     */
    public function reject(): bool
    {
        if (!$this->isPending()) {
            return false;
        }
        return $this->update([
            'status' => self::STATUS_REJECTED,
            'approved_by' => Auth::id(),
            'approved_at' => now(),
        ]);
    }

    /**
     * Mark as paid
     */
    public function markAsPaid(): bool
    {
        if (!$this->isApproved()) {
            return false;
        }
        return $this->update([
            'status' => self::STATUS_PAID,
            'paid_at' => now(),
        ]);
    }

    /**
     * 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 payslip data for PDF generation
     */
    public function getPayslipData(): array
    {
        return [
            'employee' => [
                'id' => $this->employee_id,
                'name' => $this->employee_name,
                'details' => $this->employee,
            ],
            '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->days_worked,
                'leave_given' => $this->leave_given,
                'total_days' => $this->total_days,
            ],
            'overtime' => [
                'hours' => $this->incentive_hrs,
                'rate' => $this->incentive_rate,
                'amount' => $this->incentive_amount,
            ],
            'net_salary' => $this->net_salary,
            'pay_mode' => $this->pay_mode,
            'status' => $this->status,
        ];
    }
}
