<?php
declare(strict_types=1);

namespace App\Modules\HR\Models;

use App\Core\Model;
use App\Core\App;
use App\Core\Pagination;

class HrEmployeeProfile extends Model
{
    protected static string $table = 'hr_employee_profiles';
    protected static string $primaryKey = 'id';
    protected static bool $timestamps = true;
    protected static bool $softDelete = true;
    protected static bool $autoTrackAuthor = true;

    protected static array $fillable = [
        'employee_id', 'employee_number', 'fingerprint_code', 'national_id',
        'first_name_ar', 'last_name_ar', 'first_name_en', 'last_name_en',
        'date_of_birth', 'gender', 'marital_status', 'religion', 'nationality',
        'phone', 'email', 'address',
        'education_qualification', 'education_specialization',
        'education_graduation_year', 'education_grade', 'education_university',
        'department_id', 'job_title_id', 'direct_manager_id', 'salary_structure_id',
        'hire_date', 'probation_end_date', 'probation_status',
        'employment_type', 'workforce_type', 'employment_status',
        'basic_salary', 'insurable_salary',
        'bank_name', 'bank_account_number', 'bank_iban',
        'insurance_number', 'insurance_start_date', 'tax_card_number',
        'military_status', 'has_disability', 'disability_details',
        'emergency_contact_name', 'emergency_contact_phone',
        'photo_path', 'notes',
    ];

    public static function getStatuses(): array
    {
        return [
            'active'       => 'نشط',
            'on_probation' => 'تحت الاختبار',
            'suspended'    => 'موقوف',
            'on_leave'     => 'في إجازة',
            'terminated'   => 'منتهي الخدمة',
            'resigned'     => 'مستقيل',
            'retired'      => 'متقاعد',
        ];
    }

    public static function getEmploymentStatuses(): array
    {
        return static::getStatuses();
    }

    public static function getEmploymentTypes(): array
    {
        return [
            'full_time'   => 'دوام كامل',
            'part_time'   => 'دوام جزئي',
            'contract'    => 'عقد مؤقت',
            'temporary'   => 'مؤقت',
        ];
    }

    public static function getGenders(): array
    {
        return ['male' => 'ذكر', 'female' => 'أنثى'];
    }

    public static function getMaritalStatuses(): array
    {
        return [
            'single'   => 'أعزب',
            'married'  => 'متزوج',
            'divorced' => 'مطلق',
            'widowed'  => 'أرمل',
        ];
    }

    public static function getReligions(): array
    {
        return ['muslim' => 'مسلم', 'christian' => 'مسيحي', 'other' => 'أخرى'];
    }

    public static function getMilitaryStatuses(): array
    {
        return [
            'final_exemption'     => 'إعفاء نهائي',
            'temporary_exemption' => 'إعفاء مؤقت',
            'served'              => 'أدى الخدمة',
            'not_called'          => 'لم يصبه الدور',
            'medical_unfitness'   => 'عدم اللياقة الطبية',
            'female'              => 'أنثى',
        ];
    }

    public static function getWorkforceTypes(): array
    {
        return [
            'insured'             => 'مؤمن عليه',
            'part_time_freelance' => 'غير متفرغ',
        ];
    }

    public static function findByEmployeeId(int $employeeId): ?static
    {
        $row = static::query()->where('employee_id', '=', $employeeId)->first();
        if ($row === null) {
            return null;
        }
        $instance = new static($row);
        $instance->exists = true;
        return $instance;
    }

    public static function allActive(): array
    {
        return static::query()
            ->where('employment_status', '=', 'active')
            ->orderBy('first_name_ar', 'ASC')
            ->get();
    }

    public static function getActiveIds(): array
    {
        $db = App::getInstance()->db();
        $rows = $db->select(
            "SELECT id, employee_id, first_name_ar, last_name_ar, employee_number FROM hr_employee_profiles WHERE employment_status IN ('active','on_probation') AND is_archived = 0 ORDER BY first_name_ar ASC"
        );
        return $rows;
    }

    public static function search(array $filters, int $perPage = 25, int $page = 1): array
    {
        $db = App::getInstance()->db();
        $where = 'p.is_archived = 0';
        $params = [];

        if (!empty($filters['q'])) {
            $search = '%' . $filters['q'] . '%';
            $where .= ' AND (p.first_name_ar LIKE ? OR p.last_name_ar LIKE ? OR p.first_name_en LIKE ? OR p.last_name_en LIKE ? OR p.employee_number LIKE ? OR p.national_id LIKE ?)';
            $params[] = $search;
            $params[] = $search;
            $params[] = $search;
            $params[] = $search;
            $params[] = $search;
            $params[] = $search;
        }
        if (!empty($filters['department_id'])) {
            $where .= ' AND p.department_id = ?';
            $params[] = (int) $filters['department_id'];
        }
        if (!empty($filters['employment_status'])) {
            $where .= ' AND p.employment_status = ?';
            $params[] = $filters['employment_status'];
        }
        if (!empty($filters['employment_type'])) {
            $where .= ' AND p.employment_type = ?';
            $params[] = $filters['employment_type'];
        }

        $countRow = $db->selectOne("SELECT COUNT(*) as cnt FROM hr_employee_profiles p WHERE {$where}", $params);
        $total = (int) ($countRow['cnt'] ?? 0);
        $offset = ($page - 1) * $perPage;

        $rows = $db->select(
            "SELECT p.*, d.name_ar as department_name, d.department_type, ida.name_ar as idara_name, j.name_ar as job_title_name
             FROM hr_employee_profiles p
             LEFT JOIN hr_departments d ON d.id = p.department_id
             LEFT JOIN hr_departments ida ON ida.id = d.parent_id AND ida.department_type = 'idara'
             LEFT JOIN hr_job_titles j ON j.id = p.job_title_id
             WHERE {$where}
             ORDER BY p.first_name_ar ASC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        return ['data' => $rows, 'pagination' => Pagination::paginate($total, $perPage, $page)];
    }

    public static function getYearsOfService(string $hireDate): string
    {
        $hire = new \DateTime($hireDate);
        $now = new \DateTime();
        $diff = $hire->diff($now);
        $years = $diff->y + ($diff->m / 12) + ($diff->d / 365);
        return number_format($years, 2, '.', '');
    }

    public static function getComprehensiveSalary(int $profileId): string
    {
        $db = App::getInstance()->db();
        $profile = $db->selectOne(
            "SELECT basic_salary FROM hr_employee_profiles WHERE id = ?",
            [$profileId]
        );
        if (!$profile) {
            return '0.00';
        }

        $basicSalary = $profile['basic_salary'] ?? '0.00';

        $earningsSum = $db->selectOne(
            "SELECT COALESCE(SUM(
                CASE
                    WHEN sc.calculation_type = 'fixed' THEN sd.amount
                    WHEN sc.calculation_type = 'percentage' THEN (? * COALESCE(sd.percentage, sd.amount) / 100)
                    ELSE sd.amount
                END
            ), 0) as total
            FROM hr_employee_salary_details sd
            JOIN hr_salary_components sc ON sc.id = sd.component_id
            WHERE sd.employee_profile_id = ? AND sc.type = 'earning' AND sd.is_active = 1",
            [$basicSalary, $profileId]
        );

        $earnings = $earningsSum['total'] ?? '0.00';
        return bcadd($basicSalary, (string) $earnings, 2);
    }
}
