<?php

namespace Modules\Attendance\Services;

use App\Models\ActivityLogModel;
use App\Models\AttendanceCorrectionModel;
use App\Models\AttendanceRecordModel;
use App\Models\EmployeeShiftAssignmentModel;

class AttendanceCorrectionService
{
    protected AttendanceCorrectionModel $corrections;
    protected AttendanceRecordModel $records;
    protected AttendanceService $attendance;
    protected EmployeeShiftAssignmentModel $assignments;
    protected ActivityLogModel $activity;

    public function __construct()
    {
        $this->corrections  = new AttendanceCorrectionModel();
        $this->records      = new AttendanceRecordModel();
        $this->attendance   = new AttendanceService();
        $this->assignments  = new EmployeeShiftAssignmentModel();
        $this->activity     = new ActivityLogModel();
    }

    public function request(array $input, ?int $actingUserId): array
    {
        $recordId = (int) ($input['attendance_record_id'] ?? 0);
        $record   = $this->records->find($recordId);

        if (! $record) {
            return ['success' => false, 'errors' => ['attendance_record_id' => 'Attendance record not found.']];
        }

        $reason = trim($input['reason'] ?? '');
        if (strlen($reason) < 5) {
            return ['success' => false, 'errors' => ['reason' => 'Please provide a reason (min 5 characters).']];
        }

        $date = $record['attendance_date'];
        $correctedClockIn  = $this->combineDateTime($date, $input['corrected_clock_in'] ?? null);
        $correctedClockOut = $this->combineDateTime($date, $input['corrected_clock_out'] ?? null);

        $data = [
            'attendance_record_id' => $recordId,
            'original_clock_in'    => $record['clock_in'],
            'original_clock_out'   => $record['clock_out'],
            'original_status'      => $record['status'],
            'corrected_clock_in'   => $correctedClockIn,
            'corrected_clock_out'  => $correctedClockOut,
            'corrected_status'     => $input['corrected_status'] ?? $record['status'],
            'reason'               => $reason,
            'status'               => 'pending',
            'requested_by'         => $actingUserId,
        ];

        if (! $this->corrections->insert($data)) {
            return ['success' => false, 'errors' => $this->corrections->errors()];
        }

        $id = $this->corrections->getInsertID();
        $this->activity->log('attendance_corrections', 'requested', $actingUserId, "Correction request #{$id} for record #{$recordId}", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function approve(int $id, ?int $actingUserId): array
    {
        $correction = $this->corrections->find($id);
        if (! $correction || $correction['status'] !== 'pending') {
            return ['success' => false, 'error' => 'Correction not found or already processed.'];
        }

        $record = $this->records->find($correction['attendance_record_id']);
        if (! $record) {
            return ['success' => false, 'error' => 'Attendance record not found.'];
        }

        $shift = $this->assignments->getShiftForEmployeeOnDate(
            (int) $record['employee_id'],
            $record['attendance_date']
        );

        $updated = array_merge($record, [
            'clock_in'   => $correction['corrected_clock_in'],
            'clock_out'  => $correction['corrected_clock_out'],
            'status'     => $correction['corrected_status'],
            'source'     => 'correction',
            'updated_by' => $actingUserId,
        ]);

        $updated = $this->attendance->applyMetrics($updated, $shift);
        $this->records->update($record['id'], $updated);

        $this->corrections->update($id, [
            'status'      => 'approved',
            'approved_by' => $actingUserId,
            'approved_at' => date('Y-m-d H:i:s'),
        ]);

        $this->activity->log('attendance_corrections', 'approved', $actingUserId, "Approved correction #{$id}", (string) $id);

        return ['success' => true];
    }

    public function reject(int $id, string $reason, ?int $actingUserId): array
    {
        $correction = $this->corrections->find($id);
        if (! $correction || $correction['status'] !== 'pending') {
            return ['success' => false, 'error' => 'Correction not found or already processed.'];
        }

        $this->corrections->update($id, [
            'status'           => 'rejected',
            'approved_by'      => $actingUserId,
            'approved_at'      => date('Y-m-d H:i:s'),
            'rejection_reason' => $reason ?: null,
        ]);

        $this->activity->log('attendance_corrections', 'rejected', $actingUserId, "Rejected correction #{$id}", (string) $id);

        return ['success' => true];
    }

    protected function combineDateTime(string $date, ?string $time): ?string
    {
        if (! $time || trim($time) === '') {
            return null;
        }

        return date('Y-m-d H:i:s', strtotime("{$date} {$time}"));
    }
}
