<script lang="ts">
	import { v4 as uuidv4 } from 'uuid';

	import fileSaver from 'file-saver';
	const { saveAs } = fileSaver;

	import { toast } from 'svelte-sonner';
	import { getContext, onMount } from 'svelte';
	const i18n = getContext('i18n');

	import { settings } from '$lib/stores';
	import Modal from '$lib/components/common/Modal.svelte';
	import Plus from '$lib/components/icons/Plus.svelte';
	import Minus from '$lib/components/icons/Minus.svelte';
	import PencilSolid from '$lib/components/icons/PencilSolid.svelte';
	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
	import Tooltip from '$lib/components/common/Tooltip.svelte';
	import Switch from '$lib/components/common/Switch.svelte';
	import Tags from './common/Tags.svelte';
	import { getToolServerData } from '$lib/apis';
	import { verifyToolServerConnection, registerOAuthClient } from '$lib/apis/configs';
	import AccessControlModal from '$lib/components/workspace/common/AccessControlModal.svelte';
	import LockClosed from '$lib/components/icons/LockClosed.svelte';
	import Spinner from '$lib/components/common/Spinner.svelte';
	import XMark from '$lib/components/icons/XMark.svelte';
	import Textarea from './common/Textarea.svelte';
	import ConfirmDialog from '$lib/components/common/ConfirmDialog.svelte';

	export let onSubmit: Function = () => {};
	export let onDelete: Function = () => {};

	export let show = false;
	export let edit = false;

	export let direct = false;
	export let connection = null;

	let inputElement = null;

	let type = 'openapi'; // 'openapi', 'mcp'

	let url = '';

	let spec_type = 'url'; // 'url', 'json'
	let spec = ''; // used when spec_type is 'json'
	let path = 'openapi.json';

	let auth_type = 'bearer';
	let key = '';
	let headers = '';

	let functionNameFilterList = '';
	let accessGrants = [];

	let id = '';
	let name = '';
	let description = '';

	let oauthClientInfo = null;

	let oauthClientId = '';
	let oauthClientSecret = '';
	let oauthServerUrl = '';

	let enable = true;
	let loading = false;
	let showAdvanced = false;
	let showAccessControlModal = false;
	let showDeleteConfirmDialog = false;

	const registerOAuthClientHandler = async () => {
		if (url === '') {
			toast.error($i18n.t('Please enter a valid URL'));
			return;
		}

		if (id === '') {
			toast.error($i18n.t('Please enter a valid ID'));
			return;
		}

		if (auth_type === 'oauth_2.1_static' && (!oauthClientId || !oauthClientSecret)) {
			toast.error($i18n.t('Please enter Client ID and Client Secret'));
			return;
		}

		// client_id is the tool server ID (used as the internal lookup key for both flows).
		// For static, client_secret signals the backend to use the static credential path.
		// The actual OAuth client_id/secret come from the connection info at save time.
		const formData: {
			url: string;
			client_id: string;
			client_secret?: string;
			oauth_server_url?: string;
		} = {
			url: url,
			client_id: id,
			...(auth_type === 'oauth_2.1_static'
				? { client_secret: oauthClientSecret, oauth_server_url: oauthServerUrl }
				: {})
		};

		const res = await registerOAuthClient(localStorage.token, formData, 'mcp').catch((err) => {
			toast.error($i18n.t('Registration failed'));
			return null;
		});

		if (res) {
			toast.warning(
				$i18n.t(
					'Please save the connection to persist the OAuth client information and do not change the ID'
				)
			);
			toast.success($i18n.t('Registration successful'));

			console.debug('Registration successful', res);
			oauthClientInfo = res?.oauth_client_info ?? null;
		}
	};

	const verifyHandler = async () => {
		if (url === '') {
			toast.error($i18n.t('Please enter a valid URL'));
			return;
		}

		if (['openapi', ''].includes(type)) {
			if (spec_type === 'json' && spec === '') {
				toast.error($i18n.t('Please enter a valid JSON spec'));
				return;
			}

			if (spec_type === 'url' && path === '') {
				toast.error($i18n.t('Please enter a valid path'));
				return;
			}
		}

		if (headers) {
			try {
				let _headers = JSON.parse(headers);
				if (typeof _headers !== 'object' || Array.isArray(_headers)) {
					_headers = null;
					throw new Error('Headers must be a valid JSON object');
				}
				headers = JSON.stringify(_headers, null, 2);
			} catch (error) {
				toast.error($i18n.t('Headers must be a valid JSON object'));
				return;
			}
		}

		if (direct) {
			const res = await getToolServerData(
				auth_type === 'bearer' ? key : localStorage.token,
				path.includes('://') ? path : `${url}${path.startsWith('/') ? '' : '/'}${path}`
			).catch((err) => {
				toast.error($i18n.t('Connection failed'));
			});

			if (res) {
				toast.success($i18n.t('Connection successful'));
				console.debug('Connection successful', res);
			}
		} else {
			const res = await verifyToolServerConnection(localStorage.token, {
				url,
				path,
				type,
				auth_type,
				headers: headers ? JSON.parse(headers) : undefined,
				key,
				config: {
					enable: enable,
					access_grants: accessGrants
				},
				info: {
					id,
					name,
					description
				}
			}).catch((err) => {
				toast.error($i18n.t('Connection failed'));
			});

			if (res) {
				toast.success($i18n.t('Connection successful'));
				console.debug('Connection successful', res);
			}
		}
	};

	const importHandler = async (e) => {
		const file = e.target.files[0];
		if (!file) return;

		const reader = new FileReader();
		reader.onload = (event) => {
			const json = event.target.result;
			console.log('importHandler', json);

			try {
				let data = JSON.parse(json);
				// validate data
				if (Array.isArray(data)) {
					if (data.length === 0) {
						toast.error($i18n.t('Please select a valid JSON file'));
						return;
					}
					data = data[0];
				}

				if (data.type) type = data.type;
				if (data.url) url = data.url;

				if (data.spec_type) spec_type = data.spec_type;
				if (data.spec) spec = data.spec;
				if (data.path) path = data.path;

				if (data.auth_type) auth_type = data.auth_type;
				if (data.headers) headers = JSON.stringify(data.headers, null, 2);
				if (data.key) key = data.key;

				if (data.info) {
					id = data.info.id ?? '';
					name = data.info.name ?? '';
					description = data.info.description ?? '';
				}

				if (data.config) {
					enable = data.config.enable ?? true;
					accessGrants = data.config.access_grants ?? [];
				}

				toast.success($i18n.t('Import successful'));
			} catch (error) {
				toast.error($i18n.t('Please select a valid JSON file'));
			}
		};
		reader.readAsText(file);
	};

	const exportHandler = async () => {
		// export current connection as json file
		const json = JSON.stringify([
			{
				type,
				url,

				spec_type,
				spec,
				path,

				auth_type,
				headers: headers ? JSON.parse(headers) : undefined,
				key,

				info: {
					id: id,
					name: name,
					description: description
				}
			}
		]);

		const blob = new Blob([json], {
			type: 'application/json'
		});

		saveAs(blob, `tool-server-${id || name || 'export'}.json`);
	};

	const submitHandler = async () => {
		loading = true;

		// remove trailing slash from url for non-MCP connections
		// MCP servers may require a trailing slash; stripping it can cause
		// 301 redirects that lose auth headers (see #21179)
		if (type !== 'mcp') {
			url = url.replace(/\/$/, '');
		}
		if (id.includes(':') || id.includes('|')) {
			toast.error($i18n.t('ID cannot contain ":" or "|" characters'));
			loading = false;
			return;
		}

		if (
			type === 'mcp' &&
			['oauth_2.1', 'oauth_2.1_static'].includes(auth_type) &&
			!oauthClientInfo
		) {
			toast.error($i18n.t('Please register the OAuth client'));
			loading = false;
			return;
		}

		// validate spec
		if (spec_type === 'json') {
			try {
				const specJSON = JSON.parse(spec);
				spec = JSON.stringify(specJSON, null, 2);
			} catch (e) {
				toast.error($i18n.t('Please enter a valid JSON spec'));
				loading = false;
				return;
			}
		}

		if (headers) {
			try {
				const _headers = JSON.parse(headers);
				if (typeof _headers !== 'object' || Array.isArray(_headers)) {
					throw new Error('Headers must be a valid JSON object');
				}
				headers = JSON.stringify(_headers, null, 2);
			} catch (error) {
				toast.error($i18n.t('Headers must be a valid JSON object'));
				loading = false;
				return;
			}
		}

		const connection = {
			type,
			url,

			spec_type,
			spec,
			path,

			auth_type,
			headers: headers ? JSON.parse(headers) : undefined,

			key,
			config: {
				enable: enable,
				function_name_filter_list: functionNameFilterList,
				access_grants: accessGrants
			},
			info: {
				id: id,
				name: name,
				description: description,
				...(oauthClientInfo ? { oauth_client_info: oauthClientInfo } : {}),
				...(auth_type === 'oauth_2.1_static'
					? {
							oauth_client_id: oauthClientId,
							oauth_client_secret: oauthClientSecret,
							oauth_server_url: oauthServerUrl
						}
					: {})
			}
		};

		await onSubmit(connection);

		loading = false;
		show = false;

		// reset form
		type = 'openapi';
		url = '';

		spec_type = 'url';
		spec = '';
		path = 'openapi.json';

		key = '';
		auth_type = 'bearer';

		id = '';
		name = '';
		description = '';

		oauthClientInfo = null;
		oauthClientId = '';
		oauthClientSecret = '';
		oauthServerUrl = '';

		enable = true;
		functionNameFilterList = '';
		accessGrants = [];
	};

	const init = () => {
		if (connection) {
			type = connection?.type ?? 'openapi';
			url = connection.url;

			spec_type = connection?.spec_type ?? 'url';
			spec = connection?.spec ?? '';
			path = connection?.path ?? 'openapi.json';

			auth_type = connection?.auth_type ?? 'bearer';
			headers = connection?.headers ? JSON.stringify(connection.headers, null, 2) : '';

			key = connection?.key ?? '';

			id = connection.info?.id ?? '';
			name = connection.info?.name ?? '';
			description = connection.info?.description ?? '';
			oauthClientInfo = connection.info?.oauth_client_info ?? null;
			oauthClientId = connection.info?.oauth_client_id ?? '';
			oauthClientSecret = connection.info?.oauth_client_secret ?? '';
			oauthServerUrl = connection.info?.oauth_server_url ?? '';

			enable = connection.config?.enable ?? true;
			functionNameFilterList = connection.config?.function_name_filter_list ?? '';
			accessGrants = connection.config?.access_grants ?? [];
		}
	};

	$: if (show) {
		init();
	}

	onMount(() => {
		init();
	});
</script>

<Modal size="sm" bind:show>
	<div>
		<div class=" flex justify-between dark:text-gray-100 px-5 pt-4 pb-2">
			<h1 class=" text-lg font-medium self-center font-primary">
				{#if edit}
					{$i18n.t('Edit Connection')}
				{:else}
					{$i18n.t('Add Connection')}
				{/if}
			</h1>

			<div class="flex items-center gap-3">
				<div class="flex gap-1.5 text-xs justify-end">
					<button
						class=" hover:underline"
						type="button"
						on:click={() => {
							inputElement?.click();
						}}
					>
						{$i18n.t('Import')}
					</button>

					<button class=" hover:underline" type="button" on:click={exportHandler}>
						{$i18n.t('Export')}
					</button>
				</div>
				<button
					class="self-center"
					aria-label={$i18n.t('Close Configure Connection Modal')}
					on:click={() => {
						show = false;
					}}
				>
					<XMark className={'size-5'} />
				</button>
			</div>
		</div>

		<div class="flex flex-col md:flex-row w-full px-4 pb-4 md:space-x-4 dark:text-gray-200">
			<div class=" flex flex-col w-full sm:flex-row sm:justify-center sm:space-x-6">
				<input
					bind:this={inputElement}
					type="file"
					hidden
					accept=".json"
					on:change={(e) => {
						importHandler(e);
					}}
				/>

				<form
					class="flex flex-col w-full"
					on:submit={(e) => {
						e.preventDefault();
						submitHandler();
					}}
				>
					<div class="px-1">
						<div class="flex gap-2 mb-1.5">
							<div class="flex w-full justify-between items-center">
								<div class=" text-xs text-gray-500">{$i18n.t('Type')}</div>

								<div class="">
									{#if !direct}
										<button
											on:click={() => {
												type = ['', 'openapi'].includes(type) ? 'mcp' : 'openapi';
											}}
											type="button"
											class=" text-xs text-gray-700 dark:text-gray-300"
										>
											{#if ['', 'openapi'].includes(type)}
												{$i18n.t('OpenAPI')}
											{:else if type === 'mcp'}
												{$i18n.t('MCP')}
												<span class="text-gray-500">{$i18n.t('Streamable HTTP')}</span>
											{/if}
										</button>
									{:else}
										<div class="text-xs text-gray-700 dark:text-gray-300">
											{$i18n.t('OpenAPI')}
										</div>
									{/if}
								</div>
							</div>
						</div>

						<div class="flex gap-2">
							<div class="flex flex-col flex-1">
								<div class="flex justify-between mb-0.5">
									<label
										for="enter-name"
										class={`text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
										>{$i18n.t('Name')}</label
									>
								</div>

								<div class="flex flex-1 items-center">
									<input
										id="enter-name"
										class={`w-full flex-1 text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
										type="text"
										bind:value={name}
										placeholder={$i18n.t('Enter name')}
										autocomplete="off"
									/>
								</div>
							</div>
							{#if !direct}
								<div class="flex flex-col flex-1">
									<div class="flex justify-between mb-0.5">
										<label
											for="enter-id"
											class={`text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
											>{$i18n.t('ID')}
											{#if type !== 'mcp'}<span class="opacity-50">({$i18n.t('optional')})</span
												>{/if}</label
										>
									</div>
									<div class="flex flex-1 items-center">
										<input
											id="enter-id"
											class={`w-full flex-1 text-sm bg-transparent font-mono ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
											type="text"
											bind:value={id}
											placeholder="auto"
											autocomplete="off"
											required={type === 'mcp'}
										/>
									</div>
								</div>
							{/if}
						</div>

						<div class="flex flex-col w-full mt-1 mb-1.5">
							<label
								for="description"
								class={`mb-0.5 text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
								>{$i18n.t('Description')}</label
							>

							<div class="flex-1">
								<input
									id="description"
									class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
									type="text"
									bind:value={description}
									placeholder={$i18n.t('Enter description')}
									autocomplete="off"
								/>
							</div>
						</div>

						<div class="flex gap-2">
							<div class="flex flex-col w-full">
								<div class="flex justify-between mb-0.5">
									<label
										for="api-base-url"
										class={`text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
										>{$i18n.t('URL')}</label
									>
								</div>

								<div class="flex flex-1 items-center">
									<input
										id="api-base-url"
										class={`w-full flex-1 text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
										type="text"
										bind:value={url}
										placeholder={$i18n.t('API Base URL')}
										autocomplete="off"
										required
									/>

									<Tooltip
										content={$i18n.t('Verify Connection')}
										className="shrink-0 flex items-center mr-1"
									>
										<button
											class="self-center p-1 bg-transparent hover:bg-gray-100 dark:hover:bg-gray-850 rounded-lg transition"
											on:click={() => {
												verifyHandler();
											}}
											aria-label={$i18n.t('Verify Connection')}
											type="button"
										>
											<svg
												xmlns="http://www.w3.org/2000/svg"
												viewBox="0 0 20 20"
												fill="currentColor"
												class="w-4 h-4"
												aria-hidden="true"
											>
												<path
													fill-rule="evenodd"
													d="M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0V5.36l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z"
													clip-rule="evenodd"
												/>
											</svg>
										</button>
									</Tooltip>

									<Tooltip content={enable ? $i18n.t('Enabled') : $i18n.t('Disabled')}>
										<Switch bind:state={enable} />
									</Tooltip>
								</div>
							</div>
						</div>

						<div class="flex gap-2 mt-2">
							<div class="flex flex-col w-full">
								<div class="flex justify-between items-center">
									<div class="flex gap-2 items-center">
										<div
											for="select-bearer-or-session"
											class={`text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
										>
											{$i18n.t('Auth')}
										</div>
									</div>

									{#if ['oauth_2.1', 'oauth_2.1_static'].includes(auth_type)}
										<div class="flex items-center gap-2">
											<div class="flex flex-col justify-end items-center shrink-0">
												<Tooltip
													content={oauthClientInfo
														? $i18n.t('Register Again')
														: $i18n.t('Register Client')}
												>
													<button
														class=" text-xs underline dark:text-gray-500 dark:hover:text-gray-200 text-gray-700 hover:text-gray-900 transition"
														type="button"
														on:click={() => {
															registerOAuthClientHandler();
														}}
													>
														{$i18n.t('Register Client')}
													</button>
												</Tooltip>
											</div>

											{#if !oauthClientInfo}
												<div
													class="text-xs font-medium px-1.5 rounded-md bg-yellow-500/20 text-yellow-700 dark:text-yellow-200"
												>
													{$i18n.t('Not Registered')}
												</div>
											{:else}
												<div
													class="text-xs font-medium px-1.5 rounded-md bg-green-500/20 text-green-700 dark:text-green-200"
												>
													{$i18n.t('Registered')}
												</div>
											{/if}
										</div>
									{/if}
								</div>

								<div class="flex gap-2">
									<div class="flex-shrink-0 self-start">
										<select
											id="select-bearer-or-session"
											class={`dark:bg-gray-900 w-full text-sm bg-transparent pr-5 ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
											bind:value={auth_type}
										>
											<option value="none">{$i18n.t('None')}</option>

											<option value="bearer">{$i18n.t('Bearer')}</option>
											<option value="session">{$i18n.t('Session')}</option>

											{#if !direct}
												<option value="system_oauth">{$i18n.t('OAuth')}</option>
												{#if type === 'mcp'}
													<option value="oauth_2.1">{$i18n.t('OAuth 2.1')}</option>
													<option value="oauth_2.1_static">{$i18n.t('OAuth 2.1 (Static)')}</option>
												{/if}
											{/if}
										</select>
									</div>

									<div class="flex flex-1 items-center">
										{#if auth_type === 'bearer'}
											<SensitiveInput
												bind:value={key}
												placeholder={$i18n.t('API Key')}
												required={false}
											/>
										{:else if auth_type === 'none'}
											<div
												class={`text-xs self-center translate-y-[1px] ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
											>
												{$i18n.t('No authentication')}
											</div>
										{:else if auth_type === 'session'}
											<div
												class={`text-xs self-center translate-y-[1px] ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
											>
												{$i18n.t('Forwards system user session credentials to authenticate')}
											</div>
										{:else if auth_type === 'system_oauth'}
											<div
												class={`text-xs self-center translate-y-[1px] ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
											>
												{$i18n.t('Forwards system user OAuth access token to authenticate')}
											</div>
										{:else if auth_type === 'oauth_2.1'}
											<div
												class={`flex items-center text-xs self-center translate-y-[1px] ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
											>
												{$i18n.t('Uses OAuth 2.1 Dynamic Client Registration')}
											</div>
										{:else if auth_type === 'oauth_2.1_static'}
											<div class="flex flex-col gap-1.5 w-full mt-0.5">
												<SensitiveInput
													bind:value={oauthClientId}
													placeholder={$i18n.t('Client ID')}
													required={false}
												/>
												<SensitiveInput
													bind:value={oauthClientSecret}
													placeholder={$i18n.t('Client Secret')}
													required={false}
												/>
												<div class="flex flex-1 items-center">
													<input
														class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
														type="text"
														bind:value={oauthServerUrl}
														placeholder={$i18n.t('OAuth Server URL')}
														autocomplete="off"
													/>
												</div>
											</div>
										{/if}
									</div>
								</div>
							</div>
						</div>

						<div class="flex items-center justify-between">
							<button
								type="button"
								class="flex items-center gap-1 text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition mt-2"
								on:click={() => (showAdvanced = !showAdvanced)}
							>
								<svg
									xmlns="http://www.w3.org/2000/svg"
									viewBox="0 0 20 20"
									fill="currentColor"
									class="w-3 h-3 transition-transform {showAdvanced ? 'rotate-90' : ''}"
								>
									<path
										fill-rule="evenodd"
										d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
										clip-rule="evenodd"
									/>
								</svg>
								{$i18n.t('Advanced')}
							</button>

							{#if !direct}
								<button
									class="bg-gray-50 hover:bg-gray-100 text-black dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white transition px-2 py-1 object-cover rounded-full flex gap-1 items-center mt-2"
									type="button"
									on:click={() => {
										showAccessControlModal = true;
									}}
								>
									<LockClosed strokeWidth="2.5" className="size-3.5 shrink-0" />

									<div class="text-xs font-medium shrink-0">
										{$i18n.t('Access')}
									</div>
								</button>
							{/if}
						</div>

						{#if showAdvanced}
							{#if ['', 'openapi'].includes(type)}
								<div class="flex gap-2 mt-2">
									<div class="flex flex-col w-full">
										<div class="flex justify-between items-center mb-0.5">
											<div class="flex gap-2 items-center">
												<div
													for="select-bearer-or-session"
													class={`text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
												>
													{$i18n.t('OpenAPI Spec')}
												</div>
											</div>
										</div>

										<div class="flex gap-2">
											<div class="flex-shrink-0 self-start">
												<select
													id="select-bearer-or-session"
													class={`dark:bg-gray-900 w-full text-sm bg-transparent pr-5 ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
													bind:value={spec_type}
												>
													<option value="url">{$i18n.t('URL')}</option>
													<option value="json">{$i18n.t('JSON')}</option>
												</select>
											</div>

											<div class="flex flex-1 items-center">
												{#if spec_type === 'url'}
													<div class="flex-1 flex items-center">
														<label for="url-or-path" class="sr-only"
															>{$i18n.t('openapi.json URL or Path')}</label
														>
														<input
															class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
															type="text"
															id="url-or-path"
															bind:value={path}
															placeholder={$i18n.t('openapi.json URL or Path')}
															autocomplete="off"
															required
														/>
													</div>
												{:else if spec_type === 'json'}
													<div
														class={`text-xs w-full self-center translate-y-[1px] ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
													>
														<label for="url-or-path" class="sr-only">{$i18n.t('JSON Spec')}</label>
														<textarea
															class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700 text-black dark:text-white'}`}
															bind:value={spec}
															placeholder={$i18n.t('JSON Spec')}
															autocomplete="off"
															required
															rows="5"
														/>
													</div>
												{/if}
											</div>
										</div>

										{#if ['', 'url'].includes(spec_type)}
											<div
												class={`text-xs mt-1 ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : 'text-gray-500'}`}
											>
												{$i18n.t(`WebUI will make requests to "{{url}}"`, {
													url: path.includes('://')
														? path
														: `${url}${path.startsWith('/') ? '' : '/'}${path}`
												})}
											</div>
										{/if}
									</div>
								</div>
							{/if}

							{#if !direct}
								<div class="flex gap-2 mt-2">
									<div class="flex flex-col w-full">
										<label
											for="headers-input"
											class={`mb-0.5 text-xs text-gray-500
									${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100' : ''}`}
											>{$i18n.t('Headers')}</label
										>

										<div class="flex-1">
											<Tooltip
												content={$i18n.t(
													'Enter additional headers in JSON format (e.g. {"X-Custom-Header": "value"}'
												)}
											>
												<Textarea
													className="w-full text-sm outline-hidden"
													bind:value={headers}
													placeholder={$i18n.t('Enter additional headers in JSON format')}
													required={false}
													minSize={30}
												/>
											</Tooltip>
										</div>
									</div>
								</div>
							{/if}
						{/if}

						{#if !direct}
							<hr class=" border-gray-100/50 dark:border-gray-700/10 my-2.5 w-full" />

							<div class="flex flex-col w-full mt-2">
								<label
									for="function-name-filter-list"
									class={`mb-1 text-xs ${($settings?.highContrastMode ?? false) ? 'text-gray-800 dark:text-gray-100 placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700 text-gray-500'}`}
									>{$i18n.t('Function Name Filter List')}</label
								>

								<div class="flex-1">
									<input
										id="function-name-filter-list"
										class={`w-full text-sm bg-transparent ${($settings?.highContrastMode ?? false) ? 'placeholder:text-gray-700 dark:placeholder:text-gray-100' : 'outline-hidden placeholder:text-gray-300 dark:placeholder:text-gray-700'}`}
										type="text"
										bind:value={functionNameFilterList}
										placeholder={$i18n.t('Enter function name filter list (e.g. func1, !func2)')}
										autocomplete="off"
									/>
								</div>
							</div>
						{/if}
					</div>

					{#if type === 'mcp'}
						<div
							class=" bg-yellow-500/20 text-yellow-700 dark:text-yellow-200 rounded-2xl text-xs px-4 py-3 mb-2 mt-1"
						>
							<span class="font-medium">
								{$i18n.t('Warning')}:
							</span>
							{$i18n.t(
								'MCP support is experimental and its specification changes often, which can lead to incompatibilities. OpenAPI specification support is directly maintained by the Open WebUI team, making it the more reliable option for compatibility.'
							)}

							<a class="font-medium underline" href="https://docs.openwebui.com/" target="_blank"
								>{$i18n.t('Read more →')}</a
							>
						</div>
					{/if}

					<div class="flex justify-between items-center pt-3 text-sm font-medium">
						<div>
							{#if edit}
								<button
									class="px-1 py-1.5 text-sm font-medium text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 hover:underline transition"
									type="button"
									on:click={() => {
										showDeleteConfirmDialog = true;
									}}
								>
									{$i18n.t('Delete')}
								</button>
							{/if}
						</div>

						<button
							class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full flex items-center gap-2 whitespace-nowrap {loading
								? ' cursor-not-allowed'
								: ''}"
							type="submit"
							disabled={loading}
						>
							{$i18n.t('Save')}

							{#if loading}
								<span class="shrink-0">
									<Spinner />
								</span>
							{/if}
						</button>
					</div>
				</form>
			</div>
		</div>
	</div>
</Modal>

<AccessControlModal bind:show={showAccessControlModal} bind:accessGrants />

<ConfirmDialog
	bind:show={showDeleteConfirmDialog}
	message={$i18n.t(
		'Are you sure you want to delete this connection? This action cannot be undone.'
	)}
	confirmLabel={$i18n.t('Delete')}
	on:confirm={() => {
		onDelete();
		show = false;
	}}
/>
