<?php

namespace App\Models;

use CodeIgniter\Model;

class EmployeeShiftAssignmentModel extends Model
{
    protected $table         = 'employee_shift_assignments';
    protected $primaryKey    = 'id';
    protected $returnType    = 'array';
    protected $useTimestamps = true;
    protected $dateFormat    = 'datetime';

    protected $allowedFields = [
        'employee_id', 'shift_id', 'effective_from', 'effective_to',
        'created_by', 'updated_by',
    ];

    protected $validationRules = [
        'employee_id'    => 'required|integer',
        'shift_id'       => 'required|integer',
        'effective_from' => 'required|valid_date[Y-m-d]',
    ];

    public function getShiftForEmployeeOnDate(int $employeeId, string $date): ?array
    {
        $row = $this->select('employee_shift_assignments.*, attendance_shifts.*')
            ->join('attendance_shifts', 'attendance_shifts.id = employee_shift_assignments.shift_id')
            ->where('employee_shift_assignments.employee_id', $employeeId)
            ->where('employee_shift_assignments.effective_from <=', $date)
            ->groupStart()
                ->where('employee_shift_assignments.effective_to', null)
                ->orWhere('employee_shift_assignments.effective_to >=', $date)
            ->groupEnd()
            ->where('attendance_shifts.status', 'active')
            ->orderBy('employee_shift_assignments.effective_from', 'DESC')
            ->first();

        return $row ?: null;
    }

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

        $rows = $this->select('employee_shift_assignments.*, attendance_shifts.name AS shift_name, attendance_shifts.code AS shift_code, attendance_shifts.start_time, attendance_shifts.end_time, attendance_shifts.status AS shift_status')
            ->join('attendance_shifts', 'attendance_shifts.id = employee_shift_assignments.shift_id')
            ->whereIn('employee_shift_assignments.employee_id', $employeeIds)
            ->where('employee_shift_assignments.effective_from <=', $date)
            ->groupStart()
                ->where('employee_shift_assignments.effective_to', null)
                ->orWhere('employee_shift_assignments.effective_to >=', $date)
            ->groupEnd()
            ->where('attendance_shifts.status', 'active')
            ->orderBy('employee_shift_assignments.effective_from', 'DESC')
            ->findAll();

        $map = [];
        foreach ($rows as $row) {
            $employeeId = (int) $row['employee_id'];
            if (! isset($map[$employeeId])) {
                $map[$employeeId] = $row;
            }
        }

        return $map;
    }

    public function getAssignmentsForEmployee(int $employeeId): array
    {
        return $this->select('employee_shift_assignments.*, attendance_shifts.name as shift_name, attendance_shifts.code as shift_code')
            ->join('attendance_shifts', 'attendance_shifts.id = employee_shift_assignments.shift_id')
            ->where('employee_shift_assignments.employee_id', $employeeId)
            ->orderBy('employee_shift_assignments.effective_from', 'DESC')
            ->findAll();
    }

    public function scopeForList(?int $employeeId = null, ?int $shiftId = null): self
    {
        if ($employeeId) {
            $this->where('employee_id', $employeeId);
        }

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

        return $this;
    }
}
