<?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\HrContract;
use App\Modules\HR\Models\HrEmployeeProfile;
use App\Modules\HR\Services\ContractService;

class ContractController 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 = HrContract::search($filters, 25, $page);

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

    public function create(Request $request): Response
    {
        $employeeId = (int) $request->get('employee_id', 0);
        $profile = $employeeId ? HrEmployeeProfile::find($employeeId) : null;

        return $this->view('HR.Views.contracts.form', [
            'contract'      => null,
            'profile'       => $profile,
        ]);
    }

    public function store(Request $request): Response
    {
        $data = [
            'employee_profile_id' => (int) $request->post('employee_profile_id', 0),
            'contract_type'       => trim((string) $request->post('contract_type', 'definite')),
            'start_date'          => trim((string) $request->post('start_date', '')),
            'end_date'            => trim((string) $request->post('end_date', '')) ?: null,
            'probation_months'    => (int) $request->post('probation_months', 0),
            'working_hours_per_day' => trim((string) $request->post('working_hours_per_day', '8')),
            'notice_period_months'  => (int) $request->post('notice_period_months', 2),
            'basic_salary'        => trim((string) $request->post('basic_salary', '0.00')),
            'total_package'       => trim((string) $request->post('total_package', '')) ?: null,
            'terms_ar'            => trim((string) $request->post('terms_ar', '')) ?: null,
            'notes'               => trim((string) $request->post('notes', '')) ?: null,
        ];

        $result = ContractService::create($data);

        if (!$result['success']) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', [['type' => 'error', 'message' => $result['error']]]);
            $session->flash('_old_input', $request->all());
            return $this->redirect('/hr/contracts/create');
        }

        return $this->redirect('/hr/contracts/' . $result['contract_id'])->withSuccess('تم إنشاء العقد بنجاح');
    }

    public function show(Request $request, string $id): Response
    {
        $contract = HrContract::find((int) $id);
        if (!$contract) {
            return $this->redirect('/hr/contracts')->withError('العقد غير موجود');
        }

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

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

        // Previous contract in renewal chain
        $previousContract = $contract->renewal_of_contract_id
            ? HrContract::find((int) $contract->renewal_of_contract_id)
            : null;

        // Renewal history
        $renewals = $db->select(
            "SELECT id, contract_number, start_date, end_date, status
             FROM hr_contracts
             WHERE renewal_of_contract_id = ? AND is_archived = 0
             ORDER BY start_date ASC",
            [(int) $id]
        );

        return $this->view('HR.Views.contracts.show', [
            'contract'         => $contract,
            'profile'          => $profile,
            'previousContract' => $previousContract,
            'renewals'         => $renewals,
        ]);
    }

    public function edit(Request $request, string $id): Response
    {
        $contract = HrContract::find((int) $id);
        if (!$contract) {
            return $this->redirect('/hr/contracts')->withError('العقد غير موجود');
        }

        if ($contract->status !== 'draft') {
            return $this->redirect('/hr/contracts/' . $id)->withError('لا يمكن تعديل عقد غير مسودة');
        }

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

        return $this->view('HR.Views.contracts.form', [
            'contract' => $contract,
            'profile'  => $profile,
        ]);
    }

    public function update(Request $request, string $id): Response
    {
        $contract = HrContract::find((int) $id);
        if (!$contract) {
            return $this->redirect('/hr/contracts')->withError('العقد غير موجود');
        }

        if ($contract->status !== 'draft') {
            return $this->redirect('/hr/contracts/' . $id)->withError('لا يمكن تعديل عقد غير مسودة');
        }

        $termsAr = trim((string) $request->post('terms_ar', '')) ?: null;
        $data = [
            'contract_type'          => trim((string) $request->post('contract_type', 'definite')),
            'start_date'             => trim((string) $request->post('start_date', '')),
            'end_date'               => trim((string) $request->post('end_date', '')) ?: null,
            'probation_months'       => (int) $request->post('probation_months', 0),
            'working_hours_per_day'  => trim((string) $request->post('working_hours_per_day', '8')),
            'notice_period_months'   => (int) $request->post('notice_period_months', 2),
            'basic_salary'           => trim((string) $request->post('basic_salary', '0.00')),
            'total_package'          => trim((string) $request->post('total_package', '0.00')),
            'terms_json'             => $termsAr ? json_encode($termsAr, JSON_UNESCAPED_UNICODE) : null,
            'notes'                  => trim((string) $request->post('notes', '')) ?: null,
        ];

        $errors = [];
        if ($data['start_date'] === '') {
            $errors[] = 'تاريخ بداية العقد مطلوب';
        }
        if ($data['contract_type'] === 'definite' && empty($data['end_date'])) {
            $errors[] = 'تاريخ نهاية العقد مطلوب للعقد المحدد المدة';
        }
        if ($data['probation_months'] > 3) {
            $errors[] = 'فترة الاختبار لا تتجاوز 3 أشهر (مادة 33)';
        }

        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/contracts/' . $id . '/edit');
        }

        $contract->update($data);

        return $this->redirect('/hr/contracts/' . $id)->withSuccess('تم تحديث العقد بنجاح');
    }

    public function renew(Request $request, string $id): Response
    {
        $contract = HrContract::find((int) $id);
        if (!$contract) {
            return $this->redirect('/hr/contracts')->withError('العقد غير موجود');
        }

        $newStartDate = trim((string) $request->post('new_start_date', ''));
        $newEndDate   = trim((string) $request->post('new_end_date', '')) ?: null;

        if ($newStartDate === '') {
            return $this->redirect('/hr/contracts/' . $id)->withError('تاريخ بداية العقد الجديد مطلوب');
        }

        $result = ContractService::renew((int) $id, [
            'start_date' => $newStartDate,
            'end_date'   => $newEndDate,
        ]);

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

        return $this->redirect('/hr/contracts/' . $result['contract_id'])->withSuccess('تم تجديد العقد بنجاح');
    }

    public function workReceipt(Request $request, int $id): Response
    {
        $this->authorize('hr.contract.view');

        $contract = HrContract::find($id);
        if (!$contract) {
            return $this->redirect('/hr/contracts')->withError('العقد غير موجود');
        }

        $employee = HrEmployeeProfile::find((int) $contract->employee_profile_id);
        if (!$employee) {
            return $this->redirect('/hr/contracts/' . $id)->withError('الموظف غير موجود');
        }

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

        $department = null;
        if ($employee->department_id) {
            $dept = $db->selectOne("SELECT name_ar FROM hr_departments WHERE id = ?", [(int) $employee->department_id]);
            $department = $dept['name_ar'] ?? null;
        }

        $jobTitle = null;
        if ($employee->job_title_id) {
            $jt = $db->selectOne("SELECT name_ar FROM hr_job_titles WHERE id = ?", [(int) $employee->job_title_id]);
            $jobTitle = $jt['name_ar'] ?? null;
        }

        return $this->view('HR.Views.contracts.work_receipt', [
            'contract'   => $contract,
            'employee'   => $employee,
            'department' => $department,
            'jobTitle'   => $jobTitle,
        ]);
    }

    public function terminate(Request $request, string $id): Response
    {
        $contract = HrContract::find((int) $id);
        if (!$contract) {
            return $this->redirect('/hr/contracts')->withError('العقد غير موجود');
        }

        $terminationReason = trim((string) $request->post('termination_reason', ''));

        if ($terminationReason === '') {
            return $this->redirect('/hr/contracts/' . $id)->withError('سبب إنهاء العقد مطلوب');
        }

        $result = ContractService::terminate((int) $id, $terminationReason);

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

        return $this->redirect('/hr/contracts/' . $id)->withSuccess('تم إنهاء العقد بنجاح');
    }
}
