<?php
declare(strict_types=1);

namespace App\Modules\HR\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\Logger;
use App\Modules\HR\Models\HrAttendance;
use App\Modules\HR\Models\HrEmployeeProfile;
use App\Modules\HR\Models\HrDepartment;
use App\Modules\HR\Services\AttendanceService;

class AttendanceController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'q'             => trim((string) $request->get('q', '')),
            'department_id' => trim((string) $request->get('department_id', '')),
            'date_from'     => trim((string) $request->get('date_from', date('Y-m-01'))),
            'date_to'       => trim((string) $request->get('date_to', date('Y-m-d'))),
            'status'        => trim((string) $request->get('status', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = HrAttendance::search($filters, 50, $page);

        return $this->view('HR.Views.attendance.index', [
            'records'     => $result['data'],
            'pagination'  => $result['pagination'],
            'filters'     => $filters,
            'departments' => HrDepartment::allActive(),
        ]);
    }

    public function daily(Request $request): Response
    {
        $date = trim((string) $request->get('date', date('Y-m-d')));
        $departmentId = (int) $request->get('department_id', 0);

        $db = App::getInstance()->db();

        $query = "SELECT hp.id, hp.employee_number, hp.first_name_ar, hp.last_name_ar,
                         d.name_ar as department_name,
                         a.id as attendance_id, a.check_in_time, a.check_out_time, a.status, a.actual_hours
                  FROM hr_employee_profiles hp
                  LEFT JOIN hr_departments d ON d.id = hp.department_id
                  LEFT JOIN hr_attendance a ON a.employee_profile_id = hp.id AND a.attendance_date = ? AND a.is_archived = 0
                  WHERE hp.employment_status = 'active' AND hp.is_archived = 0";
        $params = [$date];

        if ($departmentId > 0) {
            $query .= " AND hp.department_id = ?";
            $params[] = $departmentId;
        }

        $query .= " ORDER BY hp.first_name_ar ASC";
        $employees = $db->select($query, $params);

        return $this->view('HR.Views.attendance.daily', [
            'employees'   => $employees,
            'date'        => $date,
            'departmentId' => $departmentId,
            'departments' => HrDepartment::allActive(),
        ]);
    }

    public function storeDailyBulk(Request $request): Response
    {
        $date = trim((string) $request->post('date', date('Y-m-d')));
        $entries = $request->post('attendance', []);

        if (!is_array($entries) || empty($entries)) {
            return $this->redirect('/hr/attendance/daily?date=' . $date)->withError('لا توجد بيانات حضور');
        }

        $db = App::getInstance()->db();
        $employee = $this->currentEmployee();
        $successCount = 0;
        $errorCount = 0;

        foreach ($entries as $profileId => $entry) {
            $checkIn = trim((string) ($entry['check_in'] ?? ''));
            $checkOut = trim((string) ($entry['check_out'] ?? ''));

            if ($checkIn === '' && $checkOut === '') {
                continue;
            }

            try {
                // Check existing record
                $existing = $db->selectOne(
                    "SELECT id FROM hr_attendance WHERE employee_profile_id = ? AND attendance_date = ? AND is_archived = 0",
                    [(int) $profileId, $date]
                );

                $actualHours = 0.0;
                if ($checkIn !== '' && $checkOut !== '') {
                    $inTs = strtotime($date . ' ' . $checkIn);
                    $outTs = strtotime($date . ' ' . $checkOut);
                    if ($outTs > $inTs) {
                        $actualHours = round(($outTs - $inTs) / 3600, 2);
                    }
                }

                $record = [
                    'employee_profile_id' => (int) $profileId,
                    'attendance_date'     => $date,
                    'check_in_time'       => $checkIn ?: null,
                    'check_out_time'      => $checkOut ?: null,
                    'actual_hours'        => (string) $actualHours,
                    'check_in_method'     => 'manual',
                    'status'              => $checkIn !== '' ? 'present' : 'absent',
                    'updated_at'          => date('Y-m-d H:i:s'),
                    'updated_by'          => $employee ? (int) $employee->id : null,
                ];

                if ($existing) {
                    $db->update('hr_attendance', $record, '`id` = ?', [(int) $existing['id']]);
                } else {
                    $record['created_at'] = date('Y-m-d H:i:s');
                    $record['created_by'] = $employee ? (int) $employee->id : null;
                    $db->insert('hr_attendance', $record);
                }

                $successCount++;
            } catch (\Throwable $e) {
                Logger::error("Attendance entry failed for profile {$profileId}: " . $e->getMessage());
                $errorCount++;
            }
        }

        $msg = "تم تسجيل حضور {$successCount} موظف";
        if ($errorCount > 0) {
            $msg .= " (فشل {$errorCount})";
        }

        return $this->redirect('/hr/attendance/daily?date=' . $date)->withSuccess($msg);
    }

    public function edit(Request $request, string $id): Response
    {
        $attendance = HrAttendance::find((int) $id);
        if (!$attendance) {
            return $this->redirect('/hr/attendance')->withError('سجل الحضور غير موجود');
        }

        $profile = HrEmployeeProfile::find((int) $attendance->employee_profile_id);

        return $this->view('HR.Views.attendance.edit', [
            'attendance' => $attendance,
            'profile'    => $profile,
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $attendance = HrAttendance::find((int) $id);
        if (!$attendance) {
            return $this->redirect('/hr/attendance')->withError('سجل الحضور غير موجود');
        }

        $checkIn = trim((string) $request->post('check_in_time', ''));
        $checkOut = trim((string) $request->post('check_out_time', ''));

        $actualHours = 0.0;
        if ($checkIn !== '' && $checkOut !== '') {
            $inTs = strtotime($attendance->attendance_date . ' ' . $checkIn);
            $outTs = strtotime($attendance->attendance_date . ' ' . $checkOut);
            if ($outTs > $inTs) {
                $actualHours = round(($outTs - $inTs) / 3600, 2);
            }
        }

        $attendance->update([
            'check_in_time'   => $checkIn ?: null,
            'check_out_time'  => $checkOut ?: null,
            'actual_hours'    => (string) $actualHours,
            'overtime_hours'  => trim((string) $request->post('overtime_hours', '0')),
            'late_minutes'    => (int) $request->post('late_minutes', 0),
            'early_leave_minutes' => (int) $request->post('early_leave_minutes', 0),
            'status'          => trim((string) $request->post('status', 'present')),
            'notes'           => trim((string) $request->post('notes', '')) ?: null,
        ]);

        return $this->redirect('/hr/attendance')->withSuccess('تم تحديث سجل الحضور بنجاح');
    }

    public function approveBulk(Request $request): Response
    {
        $ids = $request->post('ids', []);
        if (!is_array($ids) || empty($ids)) {
            return $this->redirect('/hr/attendance')->withError('لم يتم تحديد سجلات');
        }

        $db = App::getInstance()->db();
        $employee = $this->currentEmployee();
        $count = 0;

        foreach ($ids as $id) {
            $db->update('hr_attendance', [
                'is_approved'  => 1,
                'approved_by'  => $employee ? (int) $employee->id : null,
                'approved_at'  => date('Y-m-d H:i:s'),
                'updated_at'   => date('Y-m-d H:i:s'),
            ], '`id` = ? AND `is_approved` = 0', [(int) $id]);
            $count++;
        }

        return $this->redirect('/hr/attendance')->withSuccess("تم اعتماد {$count} سجل حضور");
    }

    public function monthly(Request $request, string $employeeId): Response
    {
        $profile = HrEmployeeProfile::find((int) $employeeId);
        if (!$profile) {
            return $this->redirect('/hr/attendance')->withError('الموظف غير موجود');
        }

        $year = (int) $request->get('year', (int) date('Y'));
        $month = (int) $request->get('month', (int) date('m'));

        $records = HrAttendance::getMonthly((int) $employeeId, $year, $month);
        $summary = HrAttendance::getMonthlySummary((int) $employeeId, $year, $month);

        return $this->view('HR.Views.attendance.monthly', [
            'profile' => $profile,
            'records' => $records,
            'summary' => $summary,
            'year'    => $year,
            'month'   => $month,
        ]);
    }
}
