<?php

use MintyPHP\Buffer;
use MintyPHP\Repository\Auth\ApiTokenRepository;
use MintyPHP\Repository\Auth\RememberTokenRepository;
use MintyPHP\Router;
use MintyPHP\Service\Access\PermissionService;
use MintyPHP\Service\Settings\SettingService;
use MintyPHP\Service\Settings\SettingServicesFactory;
use MintyPHP\Support\Flash;
use MintyPHP\Support\Guard;

Guard::requireLogin();
Guard::requirePermission(PermissionService::SETTINGS_VIEW);

$rememberTokenRepository = new RememberTokenRepository();
$apiTokenRepository = new ApiTokenRepository();
$settingsFactory = new SettingServicesFactory();
$settingGateway = $settingsFactory->createSettingGateway();
$settingCacheService = $settingsFactory->createSettingCacheService();

$tenants = directoryServicesFactory()->createTenantService()->list();
$roles = directoryServicesFactory()->createRoleService()->listActive();
$departments = directoryServicesFactory()->createDepartmentService()->list();

$sortByDescription = static function ($a, $b) {
    return strcmp((string) ($a['description'] ?? ''), (string) ($b['description'] ?? ''));
};
usort($tenants, $sortByDescription);
usort($roles, $sortByDescription);
usort($departments, $sortByDescription);

$values = [
    'default_tenant_id' => $settingGateway->getDefaultTenantId(),
    'default_role_id' => $settingGateway->getDefaultRoleId(),
    'default_department_id' => $settingGateway->getDefaultDepartmentId(),
    // Read raw values for form display so existing DB values are always visible.
    'app_title' => $settingGateway->getValue(SettingService::APP_TITLE_KEY),
    'app_locale' => $settingGateway->getValue(SettingService::APP_LOCALE_KEY),
    'app_theme' => $settingGateway->getValue(SettingService::APP_THEME_KEY),
    'app_theme_user' => $settingGateway->isUserThemeAllowed(),
    'app_registration' => $settingGateway->isRegistrationEnabled(),
    'app_primary_color' => $settingGateway->getValue(SettingService::APP_PRIMARY_COLOR_KEY),
    'api_token_default_ttl_days' => $settingGateway->getApiTokenDefaultTtlDays(),
    'api_token_max_ttl_days' => $settingGateway->getApiTokenMaxTtlDays(),
    'user_inactivity_deactivate_days' => $settingGateway->getUserInactivityDeactivateDays(),
    'user_inactivity_delete_days' => $settingGateway->getUserInactivityDeleteDays(),
    'api_cors_allowed_origins' => $settingGateway->getApiCorsAllowedOriginsText(),
    'microsoft_shared_client_id' => $settingGateway->getValue(SettingService::MICROSOFT_SHARED_CLIENT_ID_KEY),
    'microsoft_authority' => $settingGateway->getMicrosoftAuthority(),
    'smtp_host' => $settingGateway->getValue(SettingService::SMTP_HOST_KEY),
    'smtp_port' => $settingGateway->getValue(SettingService::SMTP_PORT_KEY),
    'smtp_user' => $settingGateway->getValue(SettingService::SMTP_USER_KEY),
    'smtp_secure' => $settingGateway->getSmtpSecure(),
    'smtp_from' => $settingGateway->getValue(SettingService::SMTP_FROM_KEY),
    'smtp_from_name' => $settingGateway->getValue(SettingService::SMTP_FROM_NAME_KEY),
];
$activeLoginTokens = $rememberTokenRepository->countActive();
$activeApiTokens = $apiTokenRepository->countActive();
$settings = [
    'default_tenant' => $settingGateway->get(SettingService::DEFAULT_TENANT_KEY),
    'default_role' => $settingGateway->get(SettingService::DEFAULT_ROLE_KEY),
    'default_department' => $settingGateway->get(SettingService::DEFAULT_DEPARTMENT_KEY),
    'app_title' => $settingGateway->get(SettingService::APP_TITLE_KEY),
    'app_locale' => $settingGateway->get(SettingService::APP_LOCALE_KEY),
    'app_theme' => $settingGateway->get(SettingService::APP_THEME_KEY),
    'app_theme_user' => $settingGateway->get(SettingService::APP_THEME_USER_KEY),
    'app_registration' => $settingGateway->get(SettingService::APP_REGISTRATION_KEY),
    'app_primary_color' => $settingGateway->get(SettingService::APP_PRIMARY_COLOR_KEY),
    'api_token_default_ttl_days' => $settingGateway->get(SettingService::API_TOKEN_DEFAULT_TTL_DAYS_KEY),
    'api_token_max_ttl_days' => $settingGateway->get(SettingService::API_TOKEN_MAX_TTL_DAYS_KEY),
    'user_inactivity_deactivate_days' => $settingGateway->get(SettingService::USER_INACTIVITY_DEACTIVATE_DAYS_KEY),
    'user_inactivity_delete_days' => $settingGateway->get(SettingService::USER_INACTIVITY_DELETE_DAYS_KEY),
    'api_cors_allowed_origins' => $settingGateway->get(SettingService::API_CORS_ALLOWED_ORIGINS_KEY),
    'microsoft_shared_client_id' => $settingGateway->get(SettingService::MICROSOFT_SHARED_CLIENT_ID_KEY),
    'microsoft_shared_client_secret_enc' => $settingGateway->get(SettingService::MICROSOFT_SHARED_CLIENT_SECRET_ENC_KEY),
    'microsoft_authority' => $settingGateway->get(SettingService::MICROSOFT_AUTHORITY_KEY),
    'smtp_host' => $settingGateway->get(SettingService::SMTP_HOST_KEY),
    'smtp_port' => $settingGateway->get(SettingService::SMTP_PORT_KEY),
    'smtp_user' => $settingGateway->get(SettingService::SMTP_USER_KEY),
    'smtp_password' => $settingGateway->get(SettingService::SMTP_PASSWORD_KEY),
    'smtp_secure' => $settingGateway->get(SettingService::SMTP_SECURE_KEY),
    'smtp_from' => $settingGateway->get(SettingService::SMTP_FROM_KEY),
    'smtp_from_name' => $settingGateway->get(SettingService::SMTP_FROM_NAME_KEY),
];

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (!isset($_POST['settings_submit'])) {
        Router::redirect('admin/settings');
    }
    Guard::requirePermission(PermissionService::SETTINGS_UPDATE);
    $defaultTenantId = (int) ($_POST['default_tenant_id'] ?? 0);
    $defaultRoleId = (int) ($_POST['default_role_id'] ?? 0);
    $defaultDepartmentId = (int) ($_POST['default_department_id'] ?? 0);
    $appTitle = trim((string) ($_POST['app_title'] ?? ''));
    $appLocale = trim((string) ($_POST['app_locale'] ?? ''));
    $appTheme = trim((string) ($_POST['app_theme'] ?? ''));
    $appThemeUser = isset($_POST['app_theme_user']);
    $appRegistration = isset($_POST['app_registration']);
    $apiTokenDefaultTtlDays = (int) ($_POST['api_token_default_ttl_days'] ?? 0);
    $apiTokenMaxTtlDays = (int) ($_POST['api_token_max_ttl_days'] ?? 0);
    $userInactivityDeactivateDays = (int) ($_POST['user_inactivity_deactivate_days'] ?? 0);
    $userInactivityDeleteDays = (int) ($_POST['user_inactivity_delete_days'] ?? 0);
    $apiCorsAllowedOrigins = $_POST['api_cors_allowed_origins'] ?? '';
    if (is_array($apiCorsAllowedOrigins)) {
        $apiCorsAllowedOrigins = '';
    }
    $apiCorsAllowedOrigins = trim((string) $apiCorsAllowedOrigins);
    $rawPrimaryColor = $_POST['app_primary_color'] ?? '';
    if (is_array($rawPrimaryColor)) {
        $rawPrimaryColor = '';
    }
    $appPrimaryColor = trim((string) $rawPrimaryColor);
    if (in_array(strtolower($appPrimaryColor), ['null', 'undefined'], true)) {
        $appPrimaryColor = '';
    }
    $smtpHost = trim((string) ($_POST['smtp_host'] ?? ''));
    $smtpPort = (int) ($_POST['smtp_port'] ?? 0);
    $smtpUser = trim((string) ($_POST['smtp_user'] ?? ''));
    $smtpPassword = (string) ($_POST['smtp_password'] ?? '');
    $smtpSecure = trim((string) ($_POST['smtp_secure'] ?? ''));
    $smtpFrom = trim((string) ($_POST['smtp_from'] ?? ''));
    $smtpFromName = trim((string) ($_POST['smtp_from_name'] ?? ''));
    $microsoftSharedClientId = trim((string) ($_POST['microsoft_shared_client_id'] ?? ''));
    $microsoftSharedClientSecret = (string) ($_POST['microsoft_shared_client_secret'] ?? '');
    $microsoftAuthority = trim((string) ($_POST['microsoft_authority'] ?? ''));

    $settingGateway->setDefaultTenantId($defaultTenantId > 0 ? $defaultTenantId : null);
    $settingGateway->setDefaultRoleId($defaultRoleId > 0 ? $defaultRoleId : null);
    $settingGateway->setDefaultDepartmentId($defaultDepartmentId > 0 ? $defaultDepartmentId : null);
    $settingGateway->setAppTitle($appTitle);
    $settingGateway->setAppLocale($appLocale);
    $settingGateway->setAppTheme($appTheme);
    $settingGateway->setUserThemeAllowed($appThemeUser);
    $settingGateway->setRegistrationEnabled($appRegistration);
    $apiTokenMaxTtlOk = $settingGateway->setApiTokenMaxTtlDays($apiTokenMaxTtlDays > 0 ? $apiTokenMaxTtlDays : null);
    if (!$apiTokenMaxTtlOk) {
        Flash::error('API token max lifetime is invalid', 'admin/settings', 'api_token_max_ttl_invalid');
    }
    $apiTokenTtlOk = $settingGateway->setApiTokenDefaultTtlDays($apiTokenDefaultTtlDays > 0 ? $apiTokenDefaultTtlDays : null);
    if (!$apiTokenTtlOk) {
        Flash::error('API token default lifetime is invalid', 'admin/settings', 'api_token_default_ttl_invalid');
    }
    $userDeactivateOk = $settingGateway->setUserInactivityDeactivateDays($userInactivityDeactivateDays);
    if (!$userDeactivateOk) {
        Flash::error(
            'User inactivity deactivation period is invalid',
            'admin/settings',
            'user_inactivity_deactivate_days_invalid'
        );
    }
    if ($userInactivityDeactivateDays > 0) {
        $userDeleteOk = $settingGateway->setUserInactivityDeleteDays($userInactivityDeleteDays);
        if (!$userDeleteOk) {
            Flash::error(
                'User inactivity deletion period is invalid',
                'admin/settings',
                'user_inactivity_delete_days_invalid'
            );
        }
    } else {
        if ($userInactivityDeleteDays > 0) {
            Flash::error(
                'Auto-delete is ignored while auto-deactivate is disabled',
                'admin/settings',
                'user_inactivity_delete_requires_deactivate'
            );
        }
        $settingGateway->setUserInactivityDeleteDays(0);
    }
    $apiCorsOriginsOk = $settingGateway->setApiCorsAllowedOrigins($apiCorsAllowedOrigins);
    if (!$apiCorsOriginsOk) {
        Flash::error('CORS allowed origins are invalid', 'admin/settings', 'api_cors_allowed_origins_invalid');
    }
    $primaryOk = $settingGateway->setAppPrimaryColor($appPrimaryColor);
    if (!$primaryOk) {
        $appPrimaryColor = '';
        Flash::error('Primary color is invalid', 'admin/settings', 'app_primary_invalid');
    }
    $settingGateway->setSmtpHost($smtpHost);
    $settingGateway->setSmtpPort($smtpPort > 0 ? $smtpPort : null);
    $settingGateway->setSmtpUser($smtpUser);
    if (trim($smtpPassword) !== '') {
        $settingGateway->setSmtpPassword($smtpPassword);
    }
    $settingGateway->setSmtpSecure($smtpSecure);
    $settingGateway->setSmtpFrom($smtpFrom);
    $settingGateway->setSmtpFromName($smtpFromName);
    $msClientIdOk = $settingGateway->setMicrosoftSharedClientId($microsoftSharedClientId);
    if (!$msClientIdOk) {
        Flash::error('Microsoft client ID is invalid', 'admin/settings', 'microsoft_client_id_invalid');
    }
    $msAuthorityOk = $settingGateway->setMicrosoftAuthority($microsoftAuthority);
    if (!$msAuthorityOk) {
        Flash::error('Microsoft authority is invalid', 'admin/settings', 'microsoft_authority_invalid');
    }
    if (trim($microsoftSharedClientSecret) !== '') {
        try {
            $settingGateway->setMicrosoftSharedClientSecret($microsoftSharedClientSecret);
        } catch (\Throwable $exception) {
            Flash::error('Microsoft client secret could not be encrypted', 'admin/settings', 'microsoft_client_secret_invalid');
        }
    }

    $settingCacheService->update([
        'app_title' => $appTitle !== '' ? $appTitle : null,
        'app_locale' => $appLocale !== '' ? $appLocale : null,
        'app_theme' => $appTheme !== '' ? $appTheme : null,
        'app_theme_user' => $appThemeUser ? '1' : '0',
        'app_registration' => $appRegistration ? '1' : '0',
        'app_primary_color' => $appPrimaryColor !== '' ? $appPrimaryColor : null,
        'api_token_default_ttl_days' => (string) $settingGateway->getApiTokenDefaultTtlDays(),
        'api_token_max_ttl_days' => (string) $settingGateway->getApiTokenMaxTtlDays(),
        'api_cors_allowed_origins' => $settingGateway->getValue(SettingService::API_CORS_ALLOWED_ORIGINS_KEY),
    ]);

    Flash::success('Settings updated', 'admin/settings', 'settings_updated');
    Router::redirect('admin/settings');
}

Buffer::set('title', t('Settings'));
