<?php

use MintyPHP\Buffer;
use MintyPHP\I18n;
use MintyPHP\Router;
use MintyPHP\Service\Access\PermissionService;
use MintyPHP\Service\CustomField\UserCustomFieldValueService;
use MintyPHP\Service\Settings\SettingServicesFactory;
use MintyPHP\Service\User\UserServicesFactory;
use MintyPHP\Support\Flash;
use MintyPHP\Support\Guard;

Guard::requirePermissionOrForbidden(PermissionService::USERS_CREATE);
$userServicesFactory = new UserServicesFactory();
$userAccountService = $userServicesFactory->createUserAccountService();
$userAssignmentService = $userServicesFactory->createUserAssignmentService();
$userPasswordPolicyService = $userServicesFactory->createUserPasswordPolicyService();
$passwordMinLength = $userPasswordPolicyService->minLength();
$passwordHints = $userPasswordPolicyService->hints();
$settingGateway = (new SettingServicesFactory())->createSettingGateway();

$currentUserId = (int) ($_SESSION['user']['id'] ?? 0);
$allowedTenantIds = directoryServicesFactory()->createDirectoryScopeGateway()->getUserTenantIds($currentUserId);

$tenants = directoryServicesFactory()->createTenantService()->list();
if ($allowedTenantIds) {
    $tenants = array_values(array_filter($tenants, static function (array $tenant) use ($allowedTenantIds): bool {
        $tenantId = (int) ($tenant['id'] ?? 0);
        return $tenantId > 0 && in_array($tenantId, $allowedTenantIds, true);
    }));
} elseif (directoryServicesFactory()->createDirectoryScopeGateway()->isStrict()) {
    $tenants = [];
}
$roles = directoryServicesFactory()->createRoleService()->listActive();
$selectedTenantIds = [];
$selectedRoleIds = [];
$selectedDepartmentIds = [];
$departmentOptionsByTenant = [];
$canEditCustomFieldValues = permissionGateway()->userHas($currentUserId, PermissionService::CUSTOM_FIELDS_EDIT_VALUES)
    && permissionGateway()->userHas($currentUserId, PermissionService::USERS_UPDATE_ASSIGNMENTS);
$customFieldDefinitionsByTenant = [];
$customFieldValueMap = [];
$customFieldPostedValues = [
    'custom_field_values' => [],
    'custom_field_values_multi' => [],
];

$errors = [];
$form = [
    'first_name' => '',
    'last_name' => '',
    'email' => '',
    'profile_description' => '',
    'job_title' => '',
    'phone' => '',
    'mobile' => '',
    'short_dial' => '',
    'address' => '',
    'postal_code' => '',
    'city' => '',
    'country' => '',
    'region' => '',
    'hire_date' => '',
    'totp_secret' => '',
    'locale' => I18n::$locale ?? I18n::$defaultLocale,
    'active' => 1,
];

if (isset($_POST['email'])) {
    $input = $_POST;
    $tenantIds = $userAssignmentService->normalizeIdInput($input['tenant_ids'] ?? []);
    if ($allowedTenantIds) {
        $tenantIds = array_values(array_intersect($tenantIds, $allowedTenantIds));
    } elseif (directoryServicesFactory()->createDirectoryScopeGateway()->isStrict()) {
        $tenantIds = [];
    }
    $defaultTenantId = $settingGateway->getDefaultTenantId();
    if (directoryServicesFactory()->createDirectoryScopeGateway()->isStrict() && !$tenantIds && !$defaultTenantId) {
        $errors[] = t('Please select at least one tenant');
    }
    $selectedTenantIds = $tenantIds;
    $selectedRoleIds = $userAssignmentService->normalizeIdInput($input['role_ids'] ?? []);
    $selectedDepartmentIds = $userAssignmentService->normalizeIdInput($input['department_ids'] ?? []);
    $departmentOptionsByTenant = directoryServicesFactory()->createDepartmentService()->groupActiveByTenantIds($selectedTenantIds);
    $customFieldDefinitionsByTenant = UserCustomFieldValueService::buildDefinitionsByTenant($selectedTenantIds);
    $customFieldPostedValues = [
        'custom_field_values' => is_array($_POST['custom_field_values'] ?? null) ? $_POST['custom_field_values'] : [],
        'custom_field_values_multi' => is_array($_POST['custom_field_values_multi'] ?? null) ? $_POST['custom_field_values_multi'] : [],
    ];
    if ($canEditCustomFieldValues) {
        $customFieldValidationResult = UserCustomFieldValueService::validateForTenants(
            $selectedTenantIds,
            $_POST,
            true
        );
        if (!($customFieldValidationResult['ok'] ?? false)) {
            $errors = array_merge($errors, $customFieldValidationResult['errors'] ?? []);
            foreach (array_keys($form) as $fieldKey) {
                if (!array_key_exists($fieldKey, $input)) {
                    continue;
                }
                $fieldValue = $input[$fieldKey];
                if (is_scalar($fieldValue)) {
                    $form[$fieldKey] = trim((string) $fieldValue);
                }
            }
            $form['active'] = array_key_exists('active', $input) ? 1 : 0;
        }
    }
    $input['tenant_ids'] = $tenantIds;
    $input['role_ids'] = $selectedRoleIds;
    $input['department_ids'] = $selectedDepartmentIds;
    $result = ['ok' => false];
    if (!$errors) {
        $result = $userAccountService->createFromAdmin($input, $currentUserId);
        $form = $result['form'] ?? $form;
        $errors = array_merge($errors, $result['errors'] ?? []);
    }

    if (($result['ok'] ?? false) && !$errors) {
        $createdUuid = (string) ($result['uuid'] ?? '');
        if ($canEditCustomFieldValues && $createdUuid !== '') {
            $createdUser = $userAccountService->findByUuid($createdUuid);
            $createdUserId = (int) ($createdUser['id'] ?? 0);
            if ($createdUserId > 0) {
                $customFieldSyncResult = UserCustomFieldValueService::syncForUser(
                    $createdUserId,
                    $selectedTenantIds,
                    $_POST,
                    true
                );
                if (!($customFieldSyncResult['ok'] ?? false)) {
                    $syncErrors = $customFieldSyncResult['errors'] ?? [];
                    if ($syncErrors) {
                        Flash::error(
                            implode(' | ', $syncErrors),
                            "admin/users/edit/{$createdUuid}",
                            'user_custom_field_sync_failed'
                        );
                    }
                }
            }
        }
        $action = (string) ($_POST['action'] ?? 'create');
        if ($action === 'create_close') {
            Flash::success('User created', 'admin/users', 'user_created');
            Router::redirect('admin/users');
        } else {
            $uuid = $createdUuid;
            if ($uuid !== '') {
                $target = "admin/users/edit/{$uuid}";
                Flash::success('User created', $target, 'user_created');
                Router::redirect($target);
            } else {
                Flash::success('User created', 'admin/users', 'user_created');
                Router::redirect('admin/users');
            }
        }
    }
}

if (!$departmentOptionsByTenant && $selectedTenantIds) {
    $departmentOptionsByTenant = directoryServicesFactory()->createDepartmentService()->groupActiveByTenantIds($selectedTenantIds);
}
if (!$customFieldDefinitionsByTenant && $selectedTenantIds) {
    $customFieldDefinitionsByTenant = UserCustomFieldValueService::buildDefinitionsByTenant($selectedTenantIds);
}

Buffer::set('title', t('Create user'));
