<?php

namespace App\Models;

use CodeIgniter\Model;

class EmployeeModel extends Model
{
    protected $table            = 'employees';
    protected $primaryKey       = 'id';
    protected $returnType       = 'array';
    protected $useTimestamps    = true;
    protected $useSoftDeletes   = true;
    protected $dateFormat       = 'datetime';

    protected $allowedFields = [
        'employee_number', 'full_name', 'department_id', 'branch_id', 'job_title',
        'email', 'phone', 'mobile', 'cpr_number', 'nationality', 'date_of_birth',
        'gender', 'marital_status', 'address', 'city', 'country',
        'emergency_contact_name', 'emergency_contact_phone', 'hire_date',
        'employment_type', 'photo_path', 'cpr_document_path', 'bank_name',
        'bank_account', 'notes', 'user_id', 'status', 'created_by', 'updated_by',
    ];

    protected $validationRules = [
        'full_name'       => 'required|min_length[2]|max_length[200]',
        'employee_number' => 'required|max_length[30]|is_unique[employees.employee_number,id,{id}]',
        'email'           => 'permit_empty|valid_email|max_length[191]',
        'cpr_number'      => 'permit_empty|max_length[20]',
        'status'          => 'permit_empty|in_list[active,inactive,terminated,on_leave]',
    ];

    public function scopeForList(
        ?string $search = null,
        ?string $status = null,
        ?int $departmentId = null,
        ?int $branchId = null,
        bool $showTrashed = false
    ): self {
        if ($showTrashed) {
            $this->onlyDeleted();
        }

        if ($search) {
            $this->groupStart()
                ->like('full_name', $search)
                ->orLike('employee_number', $search)
                ->orLike('email', $search)
                ->orLike('cpr_number', $search)
                ->orLike('phone', $search)
                ->groupEnd();
        }

        if ($status) {
            $this->where('status', $status);
        }

        if ($departmentId) {
            $this->where('department_id', $departmentId);
        }

        if ($branchId) {
            $this->where('branch_id', $branchId);
        }

        return $this;
    }

    public function isEmployeeNumberTaken(string $number, ?int $excludeId = null): bool
    {
        $builder = $this->withDeleted()->where('employee_number', $number);
        if ($excludeId) {
            $builder->where('id !=', $excludeId);
        }

        return $builder->countAllResults() > 0;
    }

    public function isCprTaken(string $cpr, ?int $excludeId = null): bool
    {
        if ($cpr === '') {
            return false;
        }

        $builder = $this->withDeleted()->where('cpr_number', $cpr);
        if ($excludeId) {
            $builder->where('id !=', $excludeId);
        }

        return $builder->countAllResults() > 0;
    }

    public function nextSequenceForYear(int $year): int
    {
        $prefix = 'EMP-' . $year . '-';
        $rows   = $this->withDeleted()
            ->like('employee_number', $prefix, 'after')
            ->findAll();

        $max = 0;
        foreach ($rows as $row) {
            if (preg_match('/^EMP-' . $year . '-(\d+)$/', $row['employee_number'], $m)) {
                $max = max($max, (int) $m[1]);
            }
        }

        return $max + 1;
    }

    public function countByDepartment(int $departmentId): int
    {
        return $this->where('department_id', $departmentId)
            ->where('deleted_at', null)
            ->countAllResults();
    }

    public function searchActive(?string $search = null, int $limit = 100): array
    {
        return $this->scopeForList($search, 'active')
            ->orderBy('full_name', 'ASC')
            ->limit($limit)
            ->findAll();
    }

    /**
     * @param list<int|string> $ids
     */
    public function getByIds(array $ids): array
    {
        $ids = array_values(array_filter(array_map('intval', $ids)));
        if ($ids === []) {
            return [];
        }

        return $this->whereIn('id', $ids)->orderBy('full_name', 'ASC')->findAll();
    }
}
