<?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\HrEndOfService;
use App\Modules\HR\Models\HrEmployeeProfile;
use App\Modules\HR\Services\EndOfServiceService;
use App\Modules\Workflow\Services\WorkflowEngine;

class EndOfServiceController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'q'      => trim((string) $request->get('q', '')),
            'status' => trim((string) $request->get('status', '')),
            'type'   => trim((string) $request->get('type', '')),
        ];

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

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

    public function create(Request $request): Response
    {
        $employees = HrEmployeeProfile::getActiveIds();

        return $this->view('HR.Views.end_of_service.form', [
            'record'    => null,
            'employees' => $employees,
        ]);
    }

    public function store(Request $request): Response
    {
        $profileId = (int) $request->post('employee_profile_id', 0);
        $terminationType = trim((string) $request->post('termination_type', ''));
        $effectiveDate = trim((string) $request->post('effective_date', date('Y-m-d')));
        $notes = trim((string) $request->post('notes', ''));

        $errors = [];
        if ($profileId <= 0) {
            $errors[] = 'الموظف غير محدد';
        }
        if ($terminationType === '') {
            $errors[] = 'نوع إنهاء الخدمة مطلوب';
        }
        if ($effectiveDate === '') {
            $errors[] = 'تاريخ إنهاء الخدمة مطلوب';
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/hr/end-of-service/create');
        }

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

        $recordId = $db->insert('hr_end_of_service', [
            'employee_profile_id' => $profileId,
            'termination_type'    => $terminationType,
            'request_date'        => date('Y-m-d'),
            'effective_date'      => $effectiveDate,
            'notes'               => $notes ?: null,
            'years_of_service'    => '0.00',
            'last_basic_salary'   => '0.00',
            'last_total_salary'   => '0.00',
            'calculation_json'    => '{}',
            'status'              => 'draft',
            'created_at'          => date('Y-m-d H:i:s'),
            'updated_at'          => date('Y-m-d H:i:s'),
            'created_by'          => $employee ? (int) $employee->id : null,
        ]);

        if (WorkflowEngine::hasDefinition('hr_end_of_service')) {
            WorkflowEngine::createInstance('hr_end_of_service', 'hr_end_of_service', $recordId);
        }

        return $this->redirect('/hr/end-of-service/' . $recordId)->withSuccess('تم إنشاء سجل نهاية الخدمة بنجاح');
    }

    public function show(Request $request, string $id): Response
    {
        $record = HrEndOfService::find((int) $id);
        if (!$record) {
            return $this->redirect('/hr/end-of-service')->withError('السجل غير موجود');
        }

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

        $db = App::getInstance()->db();
        $approver = $record->approved_by
            ? $db->selectOne("SELECT name FROM employees WHERE id = ?", [(int) $record->approved_by])
            : null;

        return $this->view('HR.Views.end_of_service.show', [
            'record'   => $record,
            'profile'  => $profile,
            'approver' => $approver,
        ]);
    }

    public function calculate(Request $request, string $id): Response
    {
        $record = HrEndOfService::find((int) $id);
        if (!$record) {
            return $this->redirect('/hr/end-of-service')->withError('السجل غير موجود');
        }

        if (!in_array($record->status, ['draft', 'calculated'], true)) {
            return $this->redirect('/hr/end-of-service/' . $id)->withError('لا يمكن إعادة الحساب في هذه الحالة');
        }

        $result = EndOfServiceService::calculate(
            (int) $record->employee_profile_id,
            $record->termination_type,
            $record->effective_date
        );

        if (!$result['success']) {
            return $this->redirect('/hr/end-of-service/' . $id)->withError($result['error']);
        }

        $db = App::getInstance()->db();
        $db->update('hr_end_of_service', [
            'years_of_service'           => $result['years_of_service'],
            'last_basic_salary'          => $result['last_basic_salary'],
            'last_total_salary'          => $result['last_total_salary'],
            'severance_first_5y'         => $result['severance_first_5y'],
            'severance_after_5y'         => $result['severance_after_5y'],
            'total_severance'            => $result['total_severance'],
            'notice_period_compensation' => $result['notice_period_compensation'],
            'remaining_leave_days'       => $result['remaining_leave_days'],
            'leave_compensation'         => $result['leave_compensation'],
            'total_entitlement'          => $result['total_entitlement'],
            'deductions_json'            => json_encode($result['deductions_json'], JSON_UNESCAPED_UNICODE),
            'total_deductions'           => $result['total_deductions'],
            'net_settlement'             => $result['net_settlement'],
            'calculation_json'           => json_encode($result['calculation_json'], JSON_UNESCAPED_UNICODE),
            'status'                     => 'calculated',
            'updated_at'                 => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        try {
            WorkflowEngine::transitionByEntity('hr_end_of_service', (int) $id, 'calculate');
        } catch (\Throwable $e) {
            Logger::warning("Workflow transition failed for EOS calculate", ['id' => (int) $id, 'error' => $e->getMessage()]);
        }

        Logger::info("End of service calculated", ['record_id' => (int) $id, 'net_settlement' => $result['net_settlement']]);

        return $this->redirect('/hr/end-of-service/' . $id)->withSuccess(
            'تم حساب مستحقات نهاية الخدمة: ' . number_format((float) $result['net_settlement'], 2) . ' ج.م'
        );
    }

    public function approve(Request $request, string $id): Response
    {
        $record = HrEndOfService::find((int) $id);
        if (!$record) {
            return $this->redirect('/hr/end-of-service')->withError('السجل غير موجود');
        }

        if ($record->status !== 'calculated') {
            return $this->redirect('/hr/end-of-service/' . $id)->withError('يجب حساب المستحقات أولاً');
        }

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

        $db->update('hr_end_of_service', [
            'status'      => 'approved',
            '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` = ?', [(int) $id]);

        // Update employee status to terminated
        $db->update('hr_employee_profiles', [
            'employment_status'  => 'terminated',
            'termination_date'   => $record->effective_date,
            'termination_type'   => $record->termination_type,
            'termination_reason' => $record->notes,
            'updated_at'         => date('Y-m-d H:i:s'),
        ], '`id` = ? AND `is_archived` = 0', [(int) $record->employee_profile_id]);

        try {
            WorkflowEngine::transitionByEntity('hr_end_of_service', (int) $id, 'approve');
        } catch (\Throwable $e) {
            Logger::warning("Workflow transition failed for EOS approve", ['id' => (int) $id, 'error' => $e->getMessage()]);
        }

        Logger::info("End of service approved", ['record_id' => (int) $id]);

        return $this->redirect('/hr/end-of-service/' . $id)->withSuccess('تم اعتماد نهاية الخدمة');
    }

    public function markPaid(Request $request, string $id): Response
    {
        $record = HrEndOfService::find((int) $id);
        if (!$record) {
            return $this->redirect('/hr/end-of-service')->withError('السجل غير موجود');
        }

        if ($record->status !== 'approved') {
            return $this->redirect('/hr/end-of-service/' . $id)->withError('يجب اعتماد نهاية الخدمة أولاً');
        }

        $db = App::getInstance()->db();
        $employee = $this->currentEmployee();
        $paymentDate = trim((string) $request->post('payment_date', date('Y-m-d')));

        $db->update('hr_end_of_service', [
            'status'       => 'paid',
            'paid_date'    => $paymentDate,
            'updated_at'   => date('Y-m-d H:i:s'),
            'updated_by'   => $employee ? (int) $employee->id : null,
        ], '`id` = ?', [(int) $id]);

        try {
            WorkflowEngine::transitionByEntity('hr_end_of_service', (int) $id, 'mark_paid');
        } catch (\Throwable $e) {
            Logger::warning("Workflow transition failed for EOS mark_paid", ['id' => (int) $id, 'error' => $e->getMessage()]);
        }

        Logger::info("End of service paid", ['record_id' => (int) $id, 'payment_date' => $paymentDate]);

        return $this->redirect('/hr/end-of-service/' . $id)->withSuccess('تم صرف مستحقات نهاية الخدمة');
    }
}
