<?php

use MintyPHP\Buffer;
use MintyPHP\Http\SessionStoreInterface;
use MintyPHP\Module\Security\SecurityAuthorizationPolicy;
use MintyPHP\Module\Security\Service\SecurityCheckProcess;
use MintyPHP\Module\Security\Service\SecurityCheckService;
use MintyPHP\Module\Security\Service\SecurityMarkdownGateway;
use MintyPHP\Router;
use MintyPHP\Service\Access\AuthorizationService;
use MintyPHP\Session;
use MintyPHP\Support\Flash;
use MintyPHP\Support\Guard;

Guard::requireLogin();
Guard::requireAbilityOrForbidden(SecurityAuthorizationPolicy::ABILITY_CHECKS_VIEW);

$request = requestInput();
$returnTarget = requestResolveReturnTarget();
$closeTarget = requestResolveReturnTarget('security/checks');
$checkId = (int) ($id ?? 0);
$editBasePath = 'security/checks/edit/' . $checkId;
$editTarget = requestPathWithReturnTarget($editBasePath, $returnTarget);

$session = app(SessionStoreInterface::class)->all();
$tenantId = (int) ($session['current_tenant']['id'] ?? 0);
$userId = (int) ($session['user']['id'] ?? 0);

$service = app(SecurityCheckService::class);
$process = app(SecurityCheckProcess::class);
$check = $service->findById($tenantId, $checkId);

if ($check === null) {
    Flash::error(t('Security check not found'), $closeTarget, 'security_check_not_found');
    Router::redirect($closeTarget);

    return;
}

$authService = app(AuthorizationService::class);
$actorContext = ['actor_user_id' => $userId];
$canManage = $authService->authorize(SecurityAuthorizationPolicy::ABILITY_CHECKS_MANAGE, $actorContext)->isAllowed();
$canCreate = $authService->authorize(SecurityAuthorizationPolicy::ABILITY_CHECKS_CREATE, $actorContext)->isAllowed();
$canEdit = ($canManage || $canCreate) && (string) ($check['status'] ?? '') !== SecurityCheckProcess::STATUS_ARCHIVED;

if ($request->isMethod('POST')) {
    if (!Session::checkCsrfToken()) {
        Flash::error(t('Form expired, please try again'), $editTarget, 'csrf_expired');
        Router::redirect($editTarget);

        return;
    }

    $action = (string) $request->body('action', 'save');

    if ($action === 'delete') {
        if (!$canManage) {
            Flash::error(t('Permission denied'), $editTarget, 'permission_denied');
            Router::redirect($editTarget);

            return;
        }
        $service->delete($tenantId, $checkId);
        Flash::success(t('Security check deleted'), null, 'security_check_deleted');
        Router::redirect($closeTarget);

        return;
    }

    if ($action === 'archive' || $action === 'unarchive') {
        if (!$canManage) {
            Flash::error(t('Permission denied'), $editTarget, 'permission_denied');
            Router::redirect($editTarget);

            return;
        }
        $service->setArchived($tenantId, $checkId, $action === 'archive', $userId);
        Flash::success($action === 'archive' ? t('Security check archived') : t('Security check reopened'), $editTarget, 'security_check_status');
        Router::redirect($editTarget);

        return;
    }

    // Normal checklist save
    if (!$canEdit) {
        Flash::error(t('This security check cannot be edited'), $editTarget, 'not_editable');
        Router::redirect($editTarget);

        return;
    }

    $result = $service->saveState($tenantId, $checkId, [
        'step' => (array) $request->body('step', []),
        'tech' => (array) $request->body('tech', []),
    ], $userId);

    if ($result['ok'] ?? false) {
        $warning = (string) ($result['warning'] ?? '');
        if ($warning !== '') {
            Flash::add('warning', $warning, $editTarget, 'security_check_saved');
        } else {
            Flash::success(t('Security check saved'), $editTarget, 'security_check_saved');
        }
        Router::redirect($editTarget);

        return;
    }

    $firstError = reset($result['errors']) ?: t('Could not save the security check');
    Flash::error($firstError, $editTarget, 'security_check_save_failed');
    Router::redirect($editTarget);

    return;
}

// Resolve user-id → display-name for the completion log ("who completed it").
$userNames = [];
foreach ($service->listAssignableUsers($tenantId) as $assignableUser) {
    $userNames[(int) $assignableUser['id']] = (string) $assignableUser['display_name'];
}

$steps = $process->steps();
$techItems = $check['tech_items'] ?? [];

// Pre-render each checkpoint's Markdown guidance to sanitized HTML for the workspace.
$markdownGateway = app(SecurityMarkdownGateway::class);
if (is_array($check['tech_schema_snapshot']['items'] ?? null)) {
    $check['tech_schema_snapshot']['items'] = array_map(
        static function ($item) use ($markdownGateway) {
            if (
                is_array($item)
                && ($item['type'] ?? '') === 'check'
                && trim((string) ($item['markdown'] ?? '')) !== ''
            ) {
                $item['markdown_html'] = $markdownGateway->toHtml((string) $item['markdown']);
            }

            return $item;
        },
        $check['tech_schema_snapshot']['items']
    );
}
$processState = $check['process_state'] ?? [];
$techState = $check['tech_state'] ?? [];
$progress = $check['progress'] ?? [];
$status = (string) ($check['status'] ?? SecurityCheckProcess::STATUS_OPEN);

// Step 6 ("report") can produce a customer PDF only once every preceding step
// is complete. Authoritative gate; the view mirrors it and the report action
// re-checks it server-side.
$canGenerateReport = $process->reportPrerequisitesMet(
    is_array($processState) ? $processState : [],
    is_array($check['tech_schema_snapshot'] ?? null) ? $check['tech_schema_snapshot'] : [],
    is_array($techState) ? $techState : []
);
$reportPdfUrl = lurl('security/checks/report/' . $checkId);

$titleText = t('Security check') . ' — ' . (string) ($check['debitor_name'] ?? ($check['debitor_no'] ?? ''));
Buffer::set('title', $titleText);
Buffer::set('style_groups', json_encode(['security']));
$breadcrumbs = [
    ['label' => t('Home'), 'path' => 'admin'],
    ['label' => t('Security'), 'path' => 'security/checks'],
    ['label' => t('Security checks'), 'path' => 'security/checks'],
    ['label' => $titleText],
];
