<?php

use MintyPHP\Buffer;
use MintyPHP\Http\SessionStoreInterface;
use MintyPHP\Module\Helpdesk\HelpdeskAuthorizationPolicy;
use MintyPHP\Module\Helpdesk\Service\HandoverRevisionService;
use MintyPHP\Module\Helpdesk\Service\HandoverService;
use MintyPHP\Router;
use MintyPHP\Session;
use MintyPHP\Support\Flash;
use MintyPHP\Support\Guard;

Guard::requireLogin();
Guard::requireAbilityOrForbidden(HelpdeskAuthorizationPolicy::ABILITY_HANDOVERS_VIEW);

$request = requestInput();
$returnTarget = requestResolveReturnTarget();
$closeTarget = requestResolveReturnTarget('helpdesk/handovers');
$handoverId = (int) ($id ?? 0);
$editBasePath = 'helpdesk/handovers/edit/' . $handoverId;
$editTarget = requestPathWithReturnTarget($editBasePath, $returnTarget);

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

$service = app(HandoverService::class);
$revisionService = app(HandoverRevisionService::class);
$handover = $service->findById($tenantId, $handoverId);

if ($handover === null) {
    Flash::error(t('Handover not found'), $closeTarget, 'handover_not_found');
    Router::redirect($closeTarget);

    return;
}

// Determine permission level
$authService = app(\MintyPHP\Service\Access\AuthorizationService::class);
$actorContext = ['actor_user_id' => $userId];
$canManage = $authService->authorize(HelpdeskAuthorizationPolicy::ABILITY_HANDOVERS_MANAGE, $actorContext)->isAllowed();
$canCreate = $authService->authorize(HelpdeskAuthorizationPolicy::ABILITY_HANDOVERS_CREATE, $actorContext)->isAllowed();
$permissionLevel = $canManage ? HandoverService::PERMISSION_MANAGE : ($canCreate ? HandoverService::PERMISSION_CREATE : '');

$currentStatus = (string) ($handover['status'] ?? 'draft');
$canEdit = $service->canEdit($currentStatus, $permissionLevel);
$allowedStatuses = $service->getAllowedStatuses($permissionLevel);

// Parse schema snapshot
$schemaRaw = (string) ($handover['schema_snapshot'] ?? '{}');
$schema = json_decode($schemaRaw, true);
$schemaFields = is_array($schema) ? ($schema['fields'] ?? []) : [];
$schemaVersion = is_array($schema) ? (int) ($schema['version'] ?? 1) : 1;

// Parse field values
$fieldValuesRaw = (string) ($handover['field_values'] ?? '{}');
$fieldValues = json_decode($fieldValuesRaw, true);
if (!is_array($fieldValues)) {
    $fieldValues = [];
}

$errorBag = formErrors();

// Handle delete POST
if ($request->isMethod('POST') && (string) $request->body('action', '') === 'delete') {
    if (!Session::checkCsrfToken()) {
        Flash::error(t('Form expired, please try again'), $editTarget, 'csrf_expired');
        Router::redirect($editTarget);
        return;
    }

    if (!$canManage) {
        Flash::error(t('Only managers can delete handovers'), $closeTarget, 'delete_denied');
        Router::redirect($closeTarget);
        return;
    }

    $deleteResult = $service->deleteByIds($tenantId, [$handoverId], HandoverService::PERMISSION_MANAGE);
    if ($deleteResult['ok']) {
        Flash::success(t('Handover deleted'), null, 'handover_deleted');
    } else {
        Flash::error($deleteResult['error'] ?? t('Failed to delete handovers'), null, 'delete_failed');
    }
    Router::redirect($closeTarget);
    return;
}

// Handle submit-for-review POST
if ($request->isMethod('POST') && (string) $request->body('action', '') === 'submit_for_review') {
    if (!Session::checkCsrfToken()) {
        Flash::error(t('Form expired, please try again'), $editTarget, 'csrf_expired');
        Router::redirect($editTarget);
        return;
    }

    $reviewResult = $service->submitForReview($tenantId, $handoverId, $userId, $permissionLevel);
    if ($reviewResult['ok']) {
        Flash::success(t('Handover submitted for review'), $editTarget, 'handover_submitted');
    } else {
        $firstError = reset($reviewResult['errors']) ?: t('Failed to submit for review');
        Flash::error($firstError, $editTarget, 'submit_failed');
    }
    Router::redirect($editTarget);
    return;
}

// Handle restore POST
if ($request->isMethod('POST') && (string) $request->body('action', '') === 'restore') {
    if (!Session::checkCsrfToken()) {
        Flash::error(t('Form expired, please try again'), $editTarget, 'csrf_expired');
        Router::redirect($editTarget);

        return;
    }

    $restoreRevision = (int) $request->body('restore_revision', 0);
    $restoreResult = $revisionService->restoreRevision($tenantId, $handoverId, $restoreRevision, $userId, $permissionLevel);

    if ($restoreResult['ok']) {
        Flash::success(t('Version restored'), $editTarget, 'revision_restored');
    } else {
        $firstError = reset($restoreResult['errors']) ?: t('Failed to restore');
        Flash::error($firstError, $editTarget, 'revision_restore_failed');
    }

    Router::redirect($editTarget);

    return;
}

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

        return;
    }

    // Collect field values
    $submittedValues = [];
    foreach ($schemaFields as $field) {
        $key = $field['key'] ?? null;
        if ($key === null) {
            continue;
        }
        $type = $field['type'] ?? 'text';
        if ($type === 'checkbox') {
            $submittedValues[$key] = $request->body('field_' . $key, '') !== '' ? '1' : '0';
        } else {
            $submittedValues[$key] = (string) $request->body('field_' . $key, '');
        }
    }

    $fieldsChanged = $revisionService->computeDiff($fieldValues, $submittedValues) !== [];
    $updateResult = $service->updateFields($tenantId, $handoverId, $submittedValues, $userId, $permissionLevel);
    $errorBag->merge($updateResult['errors'] ?? []);

    // Handle status change
    $newStatus = (string) $request->body('status', '');
    $statusChanged = false;
    if ($newStatus !== '' && $newStatus !== $currentStatus) {
        $statusResult = $service->changeStatus($tenantId, $handoverId, $newStatus, $userId, $permissionLevel);
        $errorBag->merge($statusResult['errors'] ?? []);
        if (empty($statusResult['errors'])) {
            $statusChanged = true;
        }
    }

    if (!$errorBag->hasAny()) {
        // Create a single revision for the combined save
        $finalStatus = $statusChanged ? $newStatus : $currentStatus;
        $service->createRevisionAfterSave(
            $tenantId,
            $handoverId,
            $submittedValues,
            $finalStatus,
            $fieldsChanged,
            $statusChanged,
            $schemaVersion,
            $userId
        );

        $handover = $service->findById($tenantId, $handoverId);
        $fieldValues = $submittedValues;
        $currentStatus = (string) ($handover['status'] ?? $currentStatus);

        $action = (string) $request->body('action', 'save');
        if ($action === 'save_close') {
            Flash::success(t('Handover updated'), $closeTarget, 'handover_updated');
            Router::redirect($closeTarget);
        } else {
            Flash::success(t('Handover updated'), $editTarget, 'handover_updated');
            Router::redirect($editTarget);
        }

        return;
    }
}

$validationSummaryErrors = $errorBag->toArray();
$errors = $errorBag->toFlatList();

// Load revision data
$revisions = $revisionService->listByHandover($tenantId, $handoverId);
$activeRevisionNumber = (int) $request->query('revision', 0);
$compareRevisionNumber = (int) $request->query('compare', 0);
$isViewingRevision = $activeRevisionNumber > 0;
$activeRevision = null;
$fieldDiff = [];

if ($isViewingRevision) {
    $activeRevision = $revisionService->findRevision($tenantId, $handoverId, $activeRevisionNumber);
    if ($activeRevision === null) {
        // Invalid revision number — fall back to current
        $isViewingRevision = false;
        $activeRevisionNumber = 0;
    } else {
        // Load this revision's field values
        $revisionFieldValues = json_decode((string) ($activeRevision['field_values'] ?? '{}'), true);
        if (!is_array($revisionFieldValues)) {
            $revisionFieldValues = [];
        }

        // Compute diff
        if ($compareRevisionNumber > 0) {
            // Compare against a specific revision
            $compareRevision = $revisionService->findRevision($tenantId, $handoverId, $compareRevisionNumber);
            if ($compareRevision !== null) {
                $compareValues = json_decode((string) ($compareRevision['field_values'] ?? '{}'), true);
                if (!is_array($compareValues)) {
                    $compareValues = [];
                }
                $fieldDiff = $revisionService->computeDiff($compareValues, $revisionFieldValues);
            }
        } elseif ($activeRevisionNumber > 1) {
            // Compare against previous revision
            $prevRevision = $revisionService->findRevision($tenantId, $handoverId, $activeRevisionNumber - 1);
            if ($prevRevision !== null) {
                $prevValues = json_decode((string) ($prevRevision['field_values'] ?? '{}'), true);
                if (!is_array($prevValues)) {
                    $prevValues = [];
                }
                $fieldDiff = $revisionService->computeDiff($prevValues, $revisionFieldValues);
            }
        }

        $fieldValues = $revisionFieldValues;
        $currentStatus = (string) ($activeRevision['status'] ?? $currentStatus);
    }
}

// Can the current user submit for review?
// Assignee (create-level) or manager may submit when status is draft/in_progress.
$assignedTo = (int) ($handover['assigned_to'] ?? 0);
$isAssignee = $assignedTo === $userId;
$canSubmitForReview = !$isViewingRevision
    && ($isAssignee || $canManage)
    && in_array($currentStatus, [HandoverService::STATUS_DRAFT, HandoverService::STATUS_IN_PROGRESS], true);

$assignUrl = $canManage ? lurl('helpdesk/handovers/assign/' . $handoverId) : '';

$productCode = (string) ($handover['product_code'] ?? '');
$product = app(\MintyPHP\Module\Helpdesk\Service\SoftwareProductService::class)->findByCode($productCode);
$productName = trim((string) ($product['name'] ?? '')) !== ''
    ? $product['name']
    : (trim((string) ($product['bc_description'] ?? '')) !== '' ? $product['bc_description'] : $productCode);
$canViewSoftwareProducts = $authService->authorize(HelpdeskAuthorizationPolicy::ABILITY_SOFTWARE_PRODUCTS_MANAGE, $actorContext)->isAllowed();
$titleText = t('Handover') . ' ' . $productName;
Buffer::set('title', $titleText);
Buffer::set('style_groups', json_encode(['helpdesk']));
$breadcrumbs = [
    ['label' => t('Home'), 'path' => 'admin'],
    ['label' => t('Helpdesk'), 'path' => 'helpdesk'],
    ['label' => t('Handovers'), 'path' => 'helpdesk/handovers'],
    ['label' => $titleText],
];
