<?php
defined('BASEPATH') or exit('No direct script access allowed');

if (!function_exists('app_config_upgrade')) {
	function app_config_upgrade()
	{
		$path = APPPATH . 'config/app-config.php';
		if (!is_file($path)) {
			return app_config_create_from_legacy($path);
		}

		if (!is_readable($path) || !is_writable($path)) {
			return array(
				'success' => false,
				'changed' => false,
				'message' => 'application/config/app-config.php is not writable.',
			);
		}

		$content = file_get_contents($path);
		if ($content === false) {
			return array(
				'success' => false,
				'changed' => false,
				'message' => 'Unable to read application/config/app-config.php.',
			);
		}

		$missing = app_config_missing_definitions($content);
		if (empty($missing)) {
			$normalized = app_config_normalize_existing_content($content);
			if ($normalized !== $content) {
				$backup = $path . '.bak-' . date('YmdHis');
				@copy($path, $backup);
				if (file_put_contents($path, $normalized, LOCK_EX) === false) {
					return array(
						'success' => false,
						'changed' => false,
						'message' => 'Unable to write application/config/app-config.php.',
					);
				}

				return array(
					'success' => true,
					'changed' => true,
					'message' => 'Application config normalized successfully.',
					'backup' => is_file($backup) ? $backup : '',
				);
			}

			return array(
				'success' => true,
				'changed' => false,
				'message' => 'Application config is already up to date.',
			);
		}

		$backup = $path . '.bak-' . date('YmdHis');
		@copy($path, $backup);

		$block = "\n" . app_config_render_definitions($missing);
		$content = app_config_insert_block($content, $block);

		if (file_put_contents($path, $content, LOCK_EX) === false) {
			return array(
				'success' => false,
				'changed' => false,
				'message' => 'Unable to write application/config/app-config.php.',
			);
		}

		return array(
			'success' => true,
			'changed' => true,
			'message' => 'Application config updated successfully.',
			'backup' => is_file($backup) ? $backup : '',
		);
	}
}

if (!function_exists('app_config_create_from_legacy')) {
	function app_config_create_from_legacy($path)
	{
		$configDir = dirname($path);
		if (!is_dir($configDir) || !is_writable($configDir)) {
			return array(
				'success' => false,
				'changed' => false,
				'message' => 'application/config is not writable. Unable to create app-config.php.',
			);
		}

		$databasePath = APPPATH . 'config/database.php';
		$configPath = APPPATH . 'config/config.php';
		$databaseContent = is_readable($databasePath) ? file_get_contents($databasePath) : '';
		$configContent = is_readable($configPath) ? file_get_contents($configPath) : '';

		$values = array(
			'APP_BASE_URL' => app_config_extract_ci_config($configContent, 'base_url', app_config_guess_base_url()),
			'APP_ENC_KEY' => app_config_extract_encryption_key($configContent),
			'APP_LEGACY_PASSWORD_KEYS' => array(),
			'APP_DB_HOSTNAME' => app_config_extract_db_value($databaseContent, 'hostname', 'localhost'),
			'APP_DB_USERNAME' => app_config_extract_db_value($databaseContent, 'username', ''),
			'APP_DB_PASSWORD' => app_config_extract_db_value($databaseContent, 'password', ''),
			'APP_DB_NAME' => app_config_extract_db_value($databaseContent, 'database', ''),
			'APP_DB_CHARSET' => app_config_extract_db_value($databaseContent, 'char_set', 'utf8mb4'),
			'APP_DB_COLLATION' => app_config_extract_db_value($databaseContent, 'dbcollat', 'utf8mb4_unicode_ci'),
			'SESS_DRIVER' => app_config_extract_session_driver($configContent, true),
			'SESS_SAVE_PATH' => app_config_extract_session_save_path($configContent, true),
			'APP_SESSION_COOKIE_SAME_SITE' => 'Lax',
			'APP_CSRF_PROTECTION' => app_config_extract_ci_config_bool($configContent, 'csrf_protection', true),
		);

		if ($values['APP_BASE_URL'] !== '') {
			$values['APP_BASE_URL'] = rtrim($values['APP_BASE_URL'], '/') . '/';
		}

		if ($values['APP_DB_NAME'] === '') {
			return array(
				'success' => false,
				'changed' => false,
				'message' => 'Unable to detect the database name from application/config/database.php.',
			);
		}

		$content = app_config_render_file($values);
		if (file_put_contents($path, $content, LOCK_EX) === false) {
			return array(
				'success' => false,
				'changed' => false,
				'message' => 'Unable to create application/config/app-config.php.',
			);
		}

		return array(
			'success' => true,
			'changed' => true,
			'message' => 'Application config created from legacy config files.',
			'backup' => '',
		);
	}
}

if (!function_exists('app_config_render_file')) {
	function app_config_render_file(array $values)
	{
		$lines = array(
			'<?php',
			'',
			"defined('BASEPATH') or exit('No direct script access allowed');",
			'',
			"define('APP_BASE_URL', " . var_export($values['APP_BASE_URL'], true) . ');',
			"define('APP_ENC_KEY', " . var_export($values['APP_ENC_KEY'], true) . ');',
			"define('APP_LEGACY_PASSWORD_KEYS', " . var_export($values['APP_LEGACY_PASSWORD_KEYS'], true) . ');',
			'',
			"define('APP_DB_HOSTNAME', " . var_export($values['APP_DB_HOSTNAME'], true) . ');',
			"define('APP_DB_USERNAME', " . var_export($values['APP_DB_USERNAME'], true) . ');',
			"define('APP_DB_PASSWORD', " . var_export($values['APP_DB_PASSWORD'], true) . ');',
			"define('APP_DB_NAME', " . var_export($values['APP_DB_NAME'], true) . ');',
			"define('APP_DB_CHARSET', " . var_export($values['APP_DB_CHARSET'], true) . ');',
			"define('APP_DB_COLLATION', " . var_export($values['APP_DB_COLLATION'], true) . ');',
			'',
			"define('SESS_DRIVER', " . var_export($values['SESS_DRIVER'], true) . ');',
			"define('SESS_SAVE_PATH', " . var_export($values['SESS_SAVE_PATH'], true) . ');',
			"define('APP_SESSION_COOKIE_SAME_SITE', " . var_export($values['APP_SESSION_COOKIE_SAME_SITE'], true) . ');',
			'',
			"define('APP_CSRF_PROTECTION', " . ($values['APP_CSRF_PROTECTION'] ? 'true' : 'false') . ');',
		);

		return implode("\n", $lines) . "\n";
	}
}

if (!function_exists('app_config_normalize_existing_content')) {
	function app_config_normalize_existing_content($content)
	{
		$normalized = (string) $content;

		$normalized = preg_replace(
			"/define\\s*\\(\\s*['\"]SESS_DRIVER['\"]\\s*,\\s*['\"]files['\"]\\s*\\)\\s*;/",
			"define('SESS_DRIVER', 'database');",
			$normalized
		);

		$normalized = preg_replace(
			"/define\\s*\\(\\s*['\"]SESS_SAVE_PATH['\"]\\s*,\\s*NULL\\s*\\)\\s*;/i",
			"define('SESS_SAVE_PATH', 'tbl_sessions');",
			$normalized
		);

		return $normalized;
	}
}

if (!function_exists('app_config_missing_definitions')) {
	function app_config_missing_definitions($content)
	{
		$definitions = array(
			'APP_LEGACY_PASSWORD_KEYS' => array('value' => array('I6PnEPbQNLslYMj7ChKxDJ2yenuHLkXn'), 'after' => 'APP_ENC_KEY'),
			'APP_DB_CHARSET' => array('value' => 'utf8mb4', 'after' => 'APP_DB_NAME'),
			'APP_DB_COLLATION' => array('value' => 'utf8mb4_unicode_ci', 'after' => 'APP_DB_CHARSET'),
			'SESS_DRIVER' => array('value' => 'database', 'after' => 'APP_DB_COLLATION'),
			'SESS_SAVE_PATH' => array('value' => 'tbl_sessions', 'after' => 'SESS_DRIVER'),
			'APP_SESSION_COOKIE_SAME_SITE' => array('value' => 'Lax', 'after' => 'SESS_SAVE_PATH'),
			'APP_CSRF_PROTECTION' => array('value' => true, 'after' => 'APP_SESSION_COOKIE_SAME_SITE'),
		);

		$missing = array();
		foreach ($definitions as $name => $definition) {
			if (!preg_match("/define\\s*\\(\\s*['\"]" . preg_quote($name, '/') . "['\"]/", $content)) {
				$missing[$name] = $definition;
			}
		}

		return $missing;
	}
}

if (!function_exists('app_config_extract_db_value')) {
	function app_config_extract_db_value($content, $key, $default = '')
	{
		$pattern = "/['\"]" . preg_quote($key, '/') . "['\"]\\s*=>\\s*(['\"])(.*?)\\1/s";
		if (preg_match($pattern, (string) $content, $matches)) {
			return stripcslashes($matches[2]);
		}

		return $default;
	}
}

if (!function_exists('app_config_extract_ci_config')) {
	function app_config_extract_ci_config($content, $key, $default = '')
	{
		$pattern = "/\\\$config\\s*\\[\\s*['\"]" . preg_quote($key, '/') . "['\"]\\s*\\]\\s*=\\s*(['\"])(.*?)\\1\\s*;/s";
		if (preg_match($pattern, (string) $content, $matches)) {
			return stripcslashes($matches[2]);
		}

		return $default;
	}
}

if (!function_exists('app_config_extract_ci_config_bool')) {
	function app_config_extract_ci_config_bool($content, $key, $default = false)
	{
		$pattern = "/\\\$config\\s*\\[\\s*['\"]" . preg_quote($key, '/') . "['\"]\\s*\\]\\s*=\\s*(TRUE|FALSE|true|false|1|0)\\s*;/s";
		if (preg_match($pattern, (string) $content, $matches)) {
			$value = strtolower($matches[1]);
			return $value === 'true' || $value === '1';
		}

		return (bool) $default;
	}
}

if (!function_exists('app_config_extract_encryption_key')) {
	function app_config_extract_encryption_key($content)
	{
		$key = app_config_extract_ci_config($content, 'encryption_key', '');
		if ($key !== '') {
			return $key;
		}

		if (preg_match("/\\\$config\\s*\\[\\s*['\"]encryption_key['\"]\\s*\\]\\s*=\\s*defined\\s*\\(\\s*['\"]APP_ENC_KEY['\"]\\s*\\)\\s*\\?\\s*APP_ENC_KEY\\s*:\\s*(['\"])(.*?)\\1\\s*;/s", (string) $content, $matches)) {
			return stripcslashes($matches[2]);
		}

		return 'I6PnEPbQNLslYMj7ChKxDJ2yenuHLkXn';
	}
}

if (!function_exists('app_config_extract_session_driver')) {
	function app_config_extract_session_driver($content, $preferDatabase = false)
	{
		$driver = app_config_extract_ci_config($content, 'sess_driver', '');
		if ($driver !== '') {
			return $driver;
		}

		return app_config_extract_ci_config_bool($content, 'sess_use_database', $preferDatabase) ? 'database' : 'files';
	}
}

if (!function_exists('app_config_extract_session_save_path')) {
	function app_config_extract_session_save_path($content, $preferDatabase = false)
	{
		$savePath = app_config_extract_ci_config($content, 'sess_save_path', '');
		if ($savePath !== '') {
			return $savePath;
		}

		$table = app_config_extract_ci_config($content, 'sess_table_name', '');
		if ($table === '' && $preferDatabase) {
			return 'tbl_sessions';
		}

		return $table !== '' ? $table : null;
	}
}

if (!function_exists('app_config_guess_base_url')) {
	function app_config_guess_base_url()
	{
		if (empty($_SERVER['HTTP_HOST'])) {
			return '';
		}

		$baseUrl = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on' ? 'https' : 'http';
		$baseUrl .= '://' . $_SERVER['HTTP_HOST'];
		$script = isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : '';
		$baseUrl .= str_replace(basename($script), '', $script);

		return preg_replace('/install.*/', '', $baseUrl);
	}
}

if (!function_exists('app_config_random_key')) {
	function app_config_random_key()
	{
		try {
			return bin2hex(random_bytes(16));
		} catch (Exception $e) {
			return md5(uniqid('', true)) . md5(mt_rand());
		}
	}
}

if (!function_exists('app_config_render_definitions')) {
	function app_config_render_definitions(array $definitions)
	{
		$lines = array(
			'/*',
			'|--------------------------------------------------------------------------',
			'| Auto-added update configuration',
			'|--------------------------------------------------------------------------',
			'| These defaults were added during an update. Existing credentials and keys',
			'| are intentionally preserved.',
			'*/',
		);

		foreach ($definitions as $name => $definition) {
			$lines[] = "defined('" . $name . "') or define('" . $name . "', " . var_export($definition['value'], true) . ');';
		}

		return implode("\n", $lines) . "\n";
	}
}

if (!function_exists('app_config_insert_block')) {
	function app_config_insert_block($content, $block)
	{
		$marker = "define('APP_DB_NAME'";
		$position = strpos($content, $marker);
		if ($position === false) {
			return rtrim($content) . "\n" . $block;
		}

		$lineEnd = strpos($content, "\n", $position);
		if ($lineEnd === false) {
			return rtrim($content) . "\n" . $block;
		}

		return substr($content, 0, $lineEnd + 1) . $block . substr($content, $lineEnd + 1);
	}
}
