<script lang="ts">
	import { Button } from '$lib/components/ui/button';
	import * as Dialog from '$lib/components/ui/dialog';
	import { Input } from '$lib/components/ui/input';
	import { Label } from '$lib/components/ui/label';
	import { Switch } from '$lib/components/ui/switch';
	import * as Select from '$lib/components/ui/select';
	import { transportersApi, type Transporter } from '$lib/api/dashboard/a76/transporters';
	import { countriesApi, type Country } from '$lib/api/dashboard/reference_data/countries';
	import { statesApi, type State } from '$lib/api/dashboard/reference_data/states';
	import { companyStore } from '$lib/stores/company.svelte';
	import { browser } from '$app/environment';
	import { onMount, onDestroy } from 'svelte';

	let {
		open = $bindable(false),
		item = null,
		onSuccess
	}: {
		open: boolean;
		item?: Transporter | null;
		onSuccess?: () => void;
	} = $props();

	// Determinar si es modo edición o creación
	const isEdit = $derived(!!item);
	const title = $derived(isEdit ? 'Editar Transportista' : 'Nuevo Transportista');

	// Estado del formulario
	let formData = $state<Transporter>({
		transporter_key: '',
		name: '',
		short_name: '',
		responsible: '',
		rfc: '',
		streets: '',
		postal_code: '',
		city: '',
		state: '',
		country: '',
		loader_code: '',
		caat_code: '',
		transport_code: '',
		transport_interface_type: '',
		ftp_server: '',
		ftp_user: '',
		ftp_password: '',
		ftp_directory: '',
		filler_code: '',
		has_express_line: false
	});

	let loading = $state(false);
	let error = $state<string | null>(null);
	let fieldErrors = $state<Record<string, string>>({});
	let countries = $state<Country[]>([]);
	let states = $state<State[]>([]);
	let refsLoading = $state(false);

	const countryM3 = $derived(
		countries.find((c) => c.ame_key === formData.country)?.m3_key ?? null
	);
	const statesFiltered = $derived(
		countryM3 ? states.filter((s) => s.m3_key === countryM3) : states
	);

	async function loadReferenceData() {
		if (!browser) return;
		const companyId = companyStore.activeCompany?.id || 1;
		refsLoading = true;
		try {
			const [cc, ss] = await Promise.all([
				countriesApi.list(companyId, 1, 100),
				statesApi.list(companyId, 1, 100)
			]);
			if (cc.data?.items) countries = cc.data.items;
			if (ss.data?.items) states = ss.data.items;
		} catch {
			countries = [];
			states = [];
		} finally {
			refsLoading = false;
		}
	}

	function emptyTransporterForm(): Transporter {
		return {
			transporter_key: '',
			name: '',
			short_name: '',
			responsible: '',
			rfc: '',
			streets: '',
			postal_code: '',
			city: '',
			state: '',
			country: '',
			loader_code: '',
			caat_code: '',
			transport_code: '',
			transport_interface_type: '',
			ftp_server: '',
			ftp_user: '',
			ftp_password: '',
			ftp_directory: '',
			filler_code: '',
			has_express_line: false
		};
	}

	$effect(() => {
		if (!open) {
			error = null;
			fieldErrors = {};
			loading = false;
			return;
		}
		if (item) {
			formData = { ...item, has_express_line: item.has_express_line ?? false };
		} else {
			formData = emptyTransporterForm();
		}
		void loadReferenceData();
	});

	function validateForm(): boolean {
		const errors: Record<string, string> = {};

		// Clave del transportista
		if (!formData.transporter_key?.trim()) {
			errors.transporter_key = 'La clave es obligatoria';
		} else if (/\s/.test(formData.transporter_key)) {
			errors.transporter_key = 'La clave no puede contener espacios';
		} else if (!/^[A-Za-z0-9_-]+$/.test(formData.transporter_key)) {
			errors.transporter_key = 'La clave solo permite letras, números, guiones y guiones bajos';
		}

		// Nombre / Razón Social
		if (!formData.name?.trim()) {
			errors.name = 'El nombre o razón social es obligatorio';
		}

		// RFC (Opcional, pero si se pone debe ser válido si es MX)
		if (formData.rfc?.trim()) {
			const rfcRegex =
				/^([A-ZÑ&]{3,4}) ?(?:- ?)?(\d{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12]\d|3[01])) ?(?:- ?)?([A-Z\d]{2})([A-Z\d])$/i;
			if (formData.country === 'MEX' && !rfcRegex.test(formData.rfc.trim())) {
				errors.rfc = 'Formato de RFC inválido para México';
			}
		}

		// Código Postal
		if (formData.postal_code?.trim()) {
			if (formData.country === 'MEX' && !/^\d{5}$/.test(formData.postal_code.trim())) {
				errors.postal_code = 'El código postal en México debe ser de 5 dígitos';
			} else if (!/^\d+$/.test(formData.postal_code.trim())) {
				errors.postal_code = 'El código postal debe ser numérico';
			}
		}

		// Códigos de transporte
		if (formData.caat_code?.trim() && !/^[A-Za-z0-9]+$/.test(formData.caat_code)) {
			errors.caat_code = 'El código CAAT debe ser alfanumérico';
		}
		if (formData.transport_code?.trim() && !/^[A-Za-z0-9]+$/.test(formData.transport_code)) {
			errors.transport_code = 'El código de transporte debe ser alfanumérico';
		}
		if (formData.loader_code?.trim() && !/^[A-Za-z0-9]+$/.test(formData.loader_code)) {
			errors.loader_code = 'El código de cargador debe ser alfanumérico';
		}
		if (formData.filler_code?.trim() && !/^[A-Za-z0-9]+$/.test(formData.filler_code)) {
			errors.filler_code = 'El código de relleno debe ser alfanumérico';
		}

		// Configuración FTP
		if (formData.ftp_server?.trim()) {
			const hostRegex =
				/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
			const ipRegex =
				/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
			if (!hostRegex.test(formData.ftp_server) && !ipRegex.test(formData.ftp_server)) {
				errors.ftp_server = 'Servidor FTP inválido (debe ser un host o IP)';
			}
		}
		if (formData.ftp_user?.trim() && /\s/.test(formData.ftp_user)) {
			errors.ftp_user = 'El usuario FTP no puede contener espacios';
		}

		fieldErrors = errors;
		return Object.keys(errors).length === 0;
	}

	function clearFieldError(field: string) {
		if (fieldErrors[field]) {
			fieldErrors[field] = '';
		}
	}

	async function handleSubmit() {
		if (loading) return;
		error = null;
		fieldErrors = {};

		if (!validateForm()) {
			error = 'Por favor, corrige los errores en el formulario';
			return;
		}

		loading = true;

		try {
			const companyId = companyStore.activeCompany?.id;
			if (!companyId) {
				throw new Error('No hay una compañía seleccionada');
			}

			let response;
			if (isEdit && item) {
				response = await transportersApi.update(item.transporter_key, formData, companyId);
			} else {
				response = await transportersApi.create(formData, companyId);
			}

			if (response.error) {
				const ve = response.validationErrors;
				if (ve?.length) {
					// Mapear errores de validación del backend si están disponibles
					const backendErrors: Record<string, string> = {};
					ve.forEach((err) => {
						if (err.field) {
							backendErrors[err.field] = err.message || 'Error de validación';
						}
					});
					fieldErrors = backendErrors;
					throw new Error('Errores de validación en el servidor');
				}
				throw new Error(response.error);
			}

			// Cerrar diálogo y notificar éxito
			open = false;
			if (onSuccess) {
				onSuccess();
			}
		} catch (e) {
			error = e instanceof Error ? e.message : 'Error al guardar el transportista';
		} finally {
			loading = false;
		}
	}

	function handleCancel() {
		open = false;
		error = null;
	}

	function onSaveFormEvent() {
		void handleSubmit();
	}

	$effect(() => {
		if (!browser) return;
		document.addEventListener('save-form', onSaveFormEvent);
		return () => document.removeEventListener('save-form', onSaveFormEvent);
	});
</script>

<Dialog.Root bind:open>
	<Dialog.Content class="max-h-[90vh] overflow-y-auto sm:max-w-5xl" onInteractOutside={(e) => e.preventDefault()}>
		<Dialog.Header>
			<Dialog.Title>{title}</Dialog.Title>
			<Dialog.Description>
				{isEdit
					? 'Modifica los datos del transportista'
					: 'Completa los datos para crear un nuevo transportista'}
			</Dialog.Description>
		</Dialog.Header>

		<form
			onsubmit={(e) => {
				e.preventDefault();
				handleSubmit();
			}}
			class="space-y-6"
		>
			{#if error}
				<div class="rounded-md bg-destructive/15 p-3 text-sm text-destructive">
					{error}
				</div>
			{/if}

			<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
				<!-- Información General -->
				<section class="space-y-4">
					<h3 class="border-b pb-2 text-sm font-semibold">Información General</h3>

					<div class="grid gap-2">
						<Label for="transporter_key">Clave <span class="text-destructive">*</span></Label>
						<Input
							id="transporter_key"
							bind:value={formData.transporter_key}
							disabled={isEdit}
							aria-invalid={!!fieldErrors.transporter_key}
							oninput={() => clearFieldError('transporter_key')}
							required
							maxlength={30}
						/>
						{#if fieldErrors.transporter_key}
							<p class="text-xs text-destructive">{fieldErrors.transporter_key}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="name">Nombre / Razón Social <span class="text-destructive">*</span></Label>
						<Input
							id="name"
							bind:value={formData.name}
							aria-invalid={!!fieldErrors.name}
							oninput={() => clearFieldError('name')}
							maxlength={256}
						/>
						{#if fieldErrors.name}
							<p class="text-xs text-destructive">{fieldErrors.name}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="short_name">Nombre Corto</Label>
						<Input
							id="short_name"
							bind:value={formData.short_name}
							aria-invalid={!!fieldErrors.short_name}
							oninput={() => clearFieldError('short_name')}
							maxlength={10}
							placeholder="Máx. 10 car."
						/>
						{#if fieldErrors.short_name}
							<p class="text-xs text-destructive">{fieldErrors.short_name}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="rfc">RFC</Label>
						<Input
							id="rfc"
							bind:value={formData.rfc}
							aria-invalid={!!fieldErrors.rfc}
							oninput={() => clearFieldError('rfc')}
							maxlength={30}
						/>
						{#if fieldErrors.rfc}
							<p class="text-xs text-destructive">{fieldErrors.rfc}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="responsible">Responsable</Label>
						<Input
							id="responsible"
							bind:value={formData.responsible}
							aria-invalid={!!fieldErrors.responsible}
							oninput={() => clearFieldError('responsible')}
							maxlength={100}
						/>
						{#if fieldErrors.responsible}
							<p class="text-xs text-destructive">{fieldErrors.responsible}</p>
						{/if}
					</div>
				</section>

				<!-- Códigos y Transporte -->
				<section class="space-y-4">
					<h3 class="border-b pb-2 text-sm font-semibold">Códigos de Transporte</h3>

					<div class="grid gap-2">
						<Label for="caat_code">Código CAAT</Label>
						<Input
							id="caat_code"
							bind:value={formData.caat_code}
							aria-invalid={!!fieldErrors.caat_code}
							oninput={() => clearFieldError('caat_code')}
							maxlength={49}
						/>
						{#if fieldErrors.caat_code}
							<p class="text-xs text-destructive">{fieldErrors.caat_code}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="transport_code">Código de Transporte</Label>
						<Input
							id="transport_code"
							bind:value={formData.transport_code}
							aria-invalid={!!fieldErrors.transport_code}
							oninput={() => clearFieldError('transport_code')}
							maxlength={8}
							placeholder="Máx. 8 car."
						/>
						{#if fieldErrors.transport_code}
							<p class="text-xs text-destructive">{fieldErrors.transport_code}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="loader_code">Código Cargador</Label>
						<Input
							id="loader_code"
							bind:value={formData.loader_code}
							aria-invalid={!!fieldErrors.loader_code}
							oninput={() => clearFieldError('loader_code')}
							maxlength={9}
							placeholder="Máx. 9 car."
						/>
						{#if fieldErrors.loader_code}
							<p class="text-xs text-destructive">{fieldErrors.loader_code}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="transport_interface_type">Tipo Interfaz</Label>
						<Input
							id="transport_interface_type"
							bind:value={formData.transport_interface_type}
							aria-invalid={!!fieldErrors.transport_interface_type}
							oninput={() => clearFieldError('transport_interface_type')}
							maxlength={20}
						/>
						{#if fieldErrors.transport_interface_type}
							<p class="text-xs text-destructive">{fieldErrors.transport_interface_type}</p>
						{/if}
					</div>

					<div class="grid gap-2">
						<Label for="filler_code">Código Relleno</Label>
						<Input
							id="filler_code"
							bind:value={formData.filler_code}
							aria-invalid={!!fieldErrors.filler_code}
							oninput={() => clearFieldError('filler_code')}
							maxlength={20}
						/>
						{#if fieldErrors.filler_code}
							<p class="text-xs text-destructive">{fieldErrors.filler_code}</p>
						{/if}
					</div>

					<div class="flex items-center justify-between gap-3 rounded-lg border p-4">
						<Label for="has_express_line" class="text-sm font-medium">Carril express</Label>
						<Switch id="has_express_line" bind:checked={formData.has_express_line} />
					</div>
				</section>

				<!-- Dirección -->
				<section class="space-y-4">
					<h3 class="border-b pb-2 text-sm font-semibold">Dirección</h3>

					<div class="grid gap-2">
						<Label for="streets">Calle y Número</Label>
						<Input
							id="streets"
							bind:value={formData.streets}
							aria-invalid={!!fieldErrors.streets}
							oninput={() => clearFieldError('streets')}
							maxlength={100}
						/>
						{#if fieldErrors.streets}
							<p class="text-xs text-destructive">{fieldErrors.streets}</p>
						{/if}
					</div>

					<div class="grid grid-cols-2 gap-4">
						<div class="grid gap-2">
							<Label for="city">Ciudad</Label>
							<Input
								id="city"
								bind:value={formData.city}
								aria-invalid={!!fieldErrors.city}
								oninput={() => clearFieldError('city')}
								maxlength={30}
							/>
							{#if fieldErrors.city}
								<p class="text-xs text-destructive">{fieldErrors.city}</p>
							{/if}
						</div>
						<div class="grid gap-2">
							<Label for="country">País (clave americana)</Label>
							<Select.Root
								type="single"
								bind:value={formData.country}
								disabled={refsLoading}
								onValueChange={() => clearFieldError('country')}
							>
								<Select.Trigger
									class={fieldErrors.country ? 'border-destructive' : ''}
									id="country"
								>
									{refsLoading
										? '...'
										: formData.country
											? `${formData.country} — ${countries.find((c) => c.ame_key === formData.country)?.description_es ?? ''}`
											: '— Opcional —'}
								</Select.Trigger>
								<Select.Content class="max-h-60">
									<Select.Item value="" label="Vacío">— Vacío —</Select.Item>
									{#each countries as c}
										<Select.Item value={c.ame_key} label={c.ame_key}>
											{c.ame_key} — {c.description_es}
										</Select.Item>
									{/each}
								</Select.Content>
							</Select.Root>
							{#if fieldErrors.country}
								<p class="text-xs text-destructive">{fieldErrors.country}</p>
							{/if}
						</div>
					</div>

					<div class="grid grid-cols-2 gap-4">
						<div class="grid gap-2">
							<Label for="state">Estado / provincia</Label>
							<Select.Root
								type="single"
								bind:value={formData.state}
								disabled={refsLoading}
								onValueChange={() => clearFieldError('state')}
							>
								<Select.Trigger
									class={fieldErrors.state ? 'border-destructive' : ''}
									id="state"
								>
									{refsLoading
										? '...'
										: formData.state ||
											(formData.country ? '— Selecciona —' : '— Primero el país —')}
								</Select.Trigger>
								<Select.Content class="max-h-60">
									<Select.Item value="" label="Vacío">— Vacío —</Select.Item>
									{#each statesFiltered as s}
										<Select.Item value={s.description} label={s.description}>
											{s.description}
										</Select.Item>
									{/each}
								</Select.Content>
							</Select.Root>
							{#if fieldErrors.state}
								<p class="text-xs text-destructive">{fieldErrors.state}</p>
							{/if}
						</div>
						<div class="grid gap-2">
							<Label for="postal_code">C.P.</Label>
							<Input
								id="postal_code"
								bind:value={formData.postal_code}
								aria-invalid={!!fieldErrors.postal_code}
								oninput={() => clearFieldError('postal_code')}
								maxlength={15}
							/>
							{#if fieldErrors.postal_code}
								<p class="text-xs text-destructive">{fieldErrors.postal_code}</p>
							{/if}
						</div>
					</div>
				</section>

				<!-- Configuración FTP -->
				<section class="space-y-4">
					<h3 class="border-b pb-2 text-sm font-semibold">Configuración FTP</h3>

					<div class="grid gap-2">
						<Label for="ftp_server">Servidor FTP</Label>
						<Input
							id="ftp_server"
							bind:value={formData.ftp_server}
							aria-invalid={!!fieldErrors.ftp_server}
							oninput={() => clearFieldError('ftp_server')}
							maxlength={200}
						/>
						{#if fieldErrors.ftp_server}
							<p class="text-xs text-destructive">{fieldErrors.ftp_server}</p>
						{/if}
					</div>

					<div class="grid grid-cols-2 gap-4">
						<div class="grid gap-2">
							<Label for="ftp_user">Usuario</Label>
							<Input
								id="ftp_user"
								bind:value={formData.ftp_user}
								aria-invalid={!!fieldErrors.ftp_user}
								oninput={() => clearFieldError('ftp_user')}
								maxlength={200}
							/>
							{#if fieldErrors.ftp_user}
								<p class="text-xs text-destructive">{fieldErrors.ftp_user}</p>
							{/if}
						</div>
						<div class="grid gap-2">
							<Label for="ftp_password">Contraseña</Label>
							<Input
								id="ftp_password"
								type="password"
								bind:value={formData.ftp_password}
								aria-invalid={!!fieldErrors.ftp_password}
								oninput={() => clearFieldError('ftp_password')}
								maxlength={100}
							/>
							{#if fieldErrors.ftp_password}
								<p class="text-xs text-destructive">{fieldErrors.ftp_password}</p>
							{/if}
						</div>
					</div>

					<div class="grid gap-2">
						<Label for="ftp_directory">Directorio</Label>
						<Input
							id="ftp_directory"
							bind:value={formData.ftp_directory}
							aria-invalid={!!fieldErrors.ftp_directory}
							oninput={() => clearFieldError('ftp_directory')}
							maxlength={1000}
						/>
						{#if fieldErrors.ftp_directory}
							<p class="text-xs text-destructive">{fieldErrors.ftp_directory}</p>
						{/if}
					</div>
				</section>
			</div>

			<Dialog.Footer>
				<Button type="button" variant="outline" onclick={handleCancel} disabled={loading}>
					Cancelar
				</Button>
				<Button type="submit" disabled={loading}>
					{loading ? 'Guardando...' : isEdit ? 'Actualizar' : 'Crear'}
				</Button>
			</Dialog.Footer>
		</form>
	</Dialog.Content>
</Dialog.Root>
