<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\AccessControl;
use App\Core\Auth;
use App\Core\Csrf;
use App\Core\Request;
use App\Core\Session;
use App\Core\View;
use App\Repositories\DiarRuleSettingsRepository;
use Throwable;

final class DiarRuleSettingsController
{
    public function index(): void
    {
        Auth::requireLogin();
        AccessControl::requirePermission('diar.rules.view');
        $versionId = (int)Request::get('version_id', 0);
        try {
            $repository = new DiarRuleSettingsRepository();
            $dashboardData = $repository->dashboardData($versionId > 0 ? $versionId : null);
            $schemaReady = true;
            $loadError = '';
        } catch (Throwable $error) {
            error_log('[DiarRulesIndex] ' . $error->getMessage());
            $repository = null;
            $dashboardData = [];
            $schemaReady = false;
            $loadError = current_lang() === 'ar'
                ? 'قاعدة إعدادات DIAR المركزية غير جاهزة. شغّل حزمة DIAR-4A من مركز التحديث.'
                : 'The central DIAR settings database is not ready. Run the DIAR-4A update center.';
        }
        View::render('diar_rules/index', [
            'title' => current_lang() === 'ar' ? 'سياسة وحدود الاكتشاف' : 'Detection Policy & Thresholds',
            'activePage' => 'diar-rules',
            'schemaReady' => $schemaReady,
            'dashboardData' => $dashboardData,
            'canManage' => AccessControl::allows('diar.rules.manage'),
            'canDryRun' => AccessControl::allows('diar.rules.dry_run'),
            'canApprove' => AccessControl::allows('diar.rules.approve'),
            'canActivate' => AccessControl::allows('diar.rules.activate'),
            'successMessage' => Session::flash('diar_rules_success'),
            'errorMessage' => Session::flash('diar_rules_error') ?: $loadError,
        ]);
    }

    public function save(): void
    {
        Auth::requireLogin();
        if (!Csrf::validate((string)Request::post('_csrf', ''))) {
            $this->fail('SESSION_EXPIRED');
        }
        $action = trim((string)Request::post('action', ''));
        $versionId = (int)Request::post('version_id', 0);
        $actor = Auth::name();
        try {
            $repository = new DiarRuleSettingsRepository();
            if ($action === 'create_draft') {
                AccessControl::requirePermission('diar.rules.manage');
                $versionId = $repository->createDraft($actor, (string)Request::post('change_reason', ''));
                $this->success('DRAFT_CREATED', $versionId);
            }
            if ($action === 'save_draft') {
                AccessControl::requirePermission('diar.rules.manage');
                $params = Request::post('params', []);
                $scopes = Request::post('scopes', []);
                $repository->saveDraft(
                    $versionId,
                    is_array($params) ? $params : [],
                    is_array($scopes) ? $scopes : [],
                    $actor,
                    (string)Request::post('change_reason', '')
                );
                $this->success('DRAFT_SAVED', $versionId);
            }
            if ($action === 'request_dry_run') {
                AccessControl::requirePermission('diar.rules.dry_run');
                $runId = $repository->requestDryRun($versionId, $actor);
                Session::flash('diar_rules_success', current_lang() === 'ar'
                    ? 'تم إنشاء طلب الاختبار التجريبي رقم ' . $runId . '. لن يعتمد الإصدار قبل اكتمال الاختبار بنجاح.'
                    : 'Dry-run request ' . $runId . ' was created. The version cannot be approved before a successful result.');
                $this->redirect($versionId);
            }
            if ($action === 'approve') {
                AccessControl::requirePermission('diar.rules.approve');
                $repository->approve($versionId, $actor);
                $this->success('VERSION_APPROVED', $versionId);
            }
            if ($action === 'activate') {
                AccessControl::requirePermission('diar.rules.activate');
                $repository->activate($versionId, $actor);
                $this->success('VERSION_ACTIVATED', $versionId);
            }
            throw new \RuntimeException('INVALID_DIAR_RULE_ACTION');
        } catch (Throwable $error) {
            error_log('[DiarRulesSave] ' . $error->getMessage());
            Session::flash('diar_rules_error', $this->humanError($error->getMessage()));
            $this->redirect($versionId);
        }
    }

    private function success(string $code, int $versionId): void
    {
        $messages = [
            'DRAFT_CREATED' => ['Draft version created.', 'تم إنشاء نسخة مسودة من القواعد.'],
            'DRAFT_SAVED' => ['Draft settings saved with a new configuration hash.', 'تم حفظ إعدادات المسودة وتحديث بصمة القواعد.'],
            'VERSION_APPROVED' => ['Rule version approved.', 'تم اعتماد إصدار القواعد.'],
            'VERSION_ACTIVATED' => ['Rule version activated and the former version was retired.', 'تم تفعيل إصدار القواعد وإحالة الإصدار السابق للتقاعد.'],
        ];
        $message = $messages[$code] ?? [$code, $code];
        Session::flash('diar_rules_success', current_lang() === 'ar' ? $message[1] : $message[0]);
        $this->redirect($versionId);
    }

    private function fail(string $code): void
    {
        Session::flash('diar_rules_error', $this->humanError($code));
        $this->redirect(0);
    }

    private function humanError(string $code): string
    {
        $ar = [
            'SESSION_EXPIRED' => 'انتهت صلاحية الجلسة. برجاء إعادة المحاولة.',
            'DRAFT_VERSION_ALREADY_EXISTS' => 'توجد مسودة حالية بالفعل. راجعها قبل إنشاء مسودة جديدة.',
            'CHANGE_REASON_REQUIRED' => 'سبب التعديل مطلوب لحفظ سجل الحوكمة.',
            'PASS_DRY_RUN_REQUIRED' => 'يلزم نجاح الاختبار التجريبي قبل الاعتماد.',
            'SAVE_DRAFT_BEFORE_DRY_RUN' => 'احفظ المسودة أولًا قبل طلب الاختبار التجريبي.',
            'DIAR4A_SCHEMA_NOT_READY' => 'جداول DIAR المركزية غير مثبتة على NJCH / WATANY.',
        ];
        $en = [
            'SESSION_EXPIRED' => 'Session expired. Please try again.',
            'DRAFT_VERSION_ALREADY_EXISTS' => 'A draft already exists. Review it before creating another one.',
            'CHANGE_REASON_REQUIRED' => 'A change reason is required for governance.',
            'PASS_DRY_RUN_REQUIRED' => 'A successful dry run is required before approval.',
            'SAVE_DRAFT_BEFORE_DRY_RUN' => 'Save the draft before requesting a dry run.',
            'DIAR4A_SCHEMA_NOT_READY' => 'The central DIAR schema is not installed on NJCH / WATANY.',
        ];
        $flat = preg_replace('/\s+/', ' ', trim($code));
        return current_lang() === 'ar'
            ? ($ar[$flat] ?? 'لم يتم تنفيذ العملية. ' . $flat)
            : ($en[$flat] ?? 'The operation was not completed. ' . $flat);
    }

    private function redirect(int $versionId): void
    {
        $url = 'index.php?page=diar-rules&lang=' . current_lang();
        if ($versionId > 0) {
            $url .= '&version_id=' . $versionId;
        }
        \redirect($url);
    }
}
