<script lang="ts">
	import { onMount } from 'svelte';
	import { get } from 'svelte/store';
	import { browser } from '$app/environment';
	import { goto } from '$app/navigation';
	import { page } from '$app/stores';
	import * as Tabs from '$lib/components/ui/tabs';
	import { Button } from '$lib/components/ui/button';
	import { Badge } from '$lib/components/ui/badge';
	import { Separator } from '$lib/components/ui/separator';
	import { toast } from 'svelte-sonner';
	import { uiStore } from '$lib/stores/ui.svelte';
	import {
		ArrowLeft,
		FileText,
		DollarSign,
		Truck,
		Package,
		Eye,
		LoaderCircle,
		Save
	} from 'lucide-svelte';

	// Importar los componentes de cada pestaña
	import GeneralTabForm from '$lib/components/dashboard/invoices/edit/general-tab-form.svelte';
	import ObservationsTabForm from '$lib/components/dashboard/invoices/edit/observations-tab-form.svelte';
	import ItemsTabForm from '$lib/components/dashboard/invoices/edit/items/items-tab-form.svelte';
	import OthersTabForm from '$lib/components/dashboard/invoices/edit/others-tab-form.svelte';
	import InvoiceTopFields from '$lib/components/dashboard/invoices/edit/invoice-top-fields.svelte';
	import ContinuationTabForm from '$lib/components/dashboard/invoices/edit/continuation-tab-form.svelte';

	// Importar la API de facturas
	import type { InvoiceType } from '$lib/api/dashboard/reference_data/invoice_types';
	import type { CustomsBroker } from '$lib/api/dashboard/a76/customs-brokers';
	import type { ClientProvider } from '$lib/api/dashboard/a76/clients-providers';
	import { saveInvoice } from '$lib/components/dashboard/invoices/edit/save-invoice';
	import {
		focusInvoiceInvalidField,
		normalizeInvoiceFieldPath,
		ITEMS_LINE_PLACEHOLDER
	} from '$lib/components/dashboard/invoices/edit/focus-invoice-field';
	import { getExchangeRateByDate } from '$lib/api/dashboard/a76/exchange-rate';
	import { getExchangeRates } from '$lib/api/dashboard/a76/general_catalogs/exchange-rate';
	import ExchangeRateDialog from '$lib/components/dashboard/exchange_rate/create-edit-dialog.svelte';
	import { useShortcuts } from '$lib/hooks/use-shortcuts';
	import { obtenerAtajosEdicionFactura } from '$lib/config/shortcuts/dashboard/invoices/edit';
	import { api } from '$lib/api';
	import PrerequisitesModal from '$lib/components/dashboard/PrerequisitesModal.svelte';
	import { m } from '$lib/i18n/messages';

	// Cargar companyStore solo en el cliente - no usamos sidebar en esta página
	let companyStore: any = $state(undefined);
	let mounted = $state(false);

	onMount(async () => {
		try {
			const companyStoreModule = await import('$lib/stores/company.svelte');
			companyStore = companyStoreModule.companyStore;
			mounted = true;
		} catch (err) {
			console.error('Error loading client modules:', err);
			mounted = true;
		}
	});

	interface ExtendedPageData {
		invoiceId?: number | null;
		invoice?: any;
		isCreate?: boolean;
		invoiceTypes?: InvoiceType[];
		customsBrokers?: CustomsBroker[];
		clients?: ClientProvider[];
		providers?: ClientProvider[];
		seals?: any[];
		incoterms?: any[];
		valuationMethods?: any[];
		enclosure?: any[];
		legends?: any[];
		currencyTypes?: any[];
		transportTypes?: any[];
		transportModes?: any[];
		transporters?: any[];
		vehicles?: any[];
		drivers?: any[];
		trailers?: any[];
		customsSections?: any[];
		codePedimentoRegimens?: any[];
		user?: any;
		companies?: any[];
		authenticated?: boolean;
		filters?: {
			operation_type?: string | null;
			invoice_type?: string | null;
		};
		pedimentos?: any[];
		defaultSettings?: any;
	}

	let { data }: { data: ExtendedPageData } = $props();

	let activeTab = $state('general');
	let saving = $state(false);
	let validationHighlightField = $state<string | null>(null);

	/** Quita el anillo de error y el foco del control cuando el usuario corrige ese campo (nueva edición vs. valor al marcar error). */
	function dismissValidationHighlight(fieldKey: string) {
		if (validationHighlightField !== fieldKey) return;
		validationHighlightField = null;
		queueMicrotask(() => {
			const ae = document.activeElement as HTMLElement | null;
			if (!ae) return;
			const domId =
				fieldKey === ITEMS_LINE_PLACEHOLDER ? 'invoice-items-tab-root' : fieldKey;
			const host = document.getElementById(domId);
			if (host && (host === ae || host.contains(ae))) {
				ae.blur();
			}
		});
	}

	// ID de la factura
	let invoiceId = $state<number | null>(data.invoiceId ?? null);

	// Sincronizar el ID de la factura si cambia en los props (ej: después de un primer guardado)
	$effect(() => {
		if (data.invoiceId && data.invoiceId !== invoiceId) {
			invoiceId = data.invoiceId;
		}
	});

	// Form Skeletons for robust initialization
	const topFieldsSkeleton = {
		is_pedimento_pending: false,
		pedimento_id: '',
		remesa: '',
		invoice_number: '',
		invoice_date: new Date().toISOString().split('T')[0],
		emission_date: new Date().toISOString().split('T')[0],
		operation_type: data.filters?.operation_type || '',
		invoice_type: data.filters?.invoice_type || '',
		fecha_pedimento_del: '',
		fecha_pedimento_al: '',
		clave_pedimento: '',
		regimen_pedimento: ''
	};

	const generalSkeleton = {
		provider_header: 'proveedor',
		provider_id: null,
		sold_to_header: 'consignado_a',
		sold_to_id: null,
		shipped_to_header: 'enviado_a',
		shipped_to_id: null,
		customs_broker_id: null,
		customs_broker_us_id: null,
		currency_type: '',
		currency: 'foreign',
		exchange_rate: null,
		weight_type: 'kgs',
		iva_factor: null,
		carrier_id: null,
		transport_id: '',
		driver_name: '',
		transport_type: '',
		trailer_num: '',
		aduana: '',
		document_type: ''
	};

	const observationSkeleton = {
		observation_es: '',
		observation_en: '',
		freight: null,
		insurance_value: null,
		insurance: null,
		packaging: null,
		other_increments: null,
		total_increments_mn: null,
		total_increments_me: null,
		incoterm: null,
		enclosure: null,
		num_seals: null,
		movement_type: '',
		alternate_invoice: '',
		valuation_method: null
	};

	const othersSkeleton = {
		comments_status: '',
		transport_mode: 'TRUCK',
		is_mixed: false,
		print_stamp: false,
		rule_3121_parties_ii: false,
		related_doc_id: null,
		code_signature: '',
		electronic_signature: '',
		mandatory_person: '',
		contingency_mode: false,
		cove: '',
		operation_num: '',
		adendas: '',
		observations_vu: '',
		certified_number: '',
		// Export fields
		bill_number: '',
		guide_number: '',
		shipment_number: '',
		option_iv18: '',
		delivered_status: false,
		received_by: '',
		delivery_date: ''
	};

	const continuationSkeleton = {
		numero_tipo_transporte: '',
		es_ferrocarril: 'no',
		numero_bl: '',
		cantidad_guias_embarque: null,
		destino_origen: '',
		puerto_entrada: '',
		vehicle_data: '',
		fue_revisado_equipo: false,
		sub_division: false,
		funge_como_cd: false,
		llego_pedimento: false,
		errores_facturacion: [],
		semaforo_verde_aduana_mexicana: false,
		semaforo_verde_aduana_americana: false,
		semaforo_rojo_aduana_mexicana: false,
		semaforo_rojo_aduana_americana: false,
		// Export fields
		is_mixed: false,
		reason_export: '1',
		purchase_order: '',
		payment_terms: '',
		handling_fees: 0,
		cfdi_uuid: '',
		path_pdf: '',
		path_xml: ''
	};

	function ensureItemsFormData(initial?: any) {
		const base = initial ? { ...initial } : {};
		if (!Array.isArray(base.items)) {
			base.items = [];
		}
		return base;
	}

	function mergeDefaults(skeleton: any, partial: any) {
		if (!partial) return skeleton;
		// Filter out undefined values from partial to preserve skeleton defaults
		const filtered = Object.fromEntries(
			Object.entries(partial).filter(([_, value]) => value !== undefined)
		);
		// Compat: remolque vivía en transport_num en layouts antiguos
		if (filtered.trailer_num === undefined && filtered.transport_num !== undefined) {
			filtered.trailer_num = filtered.transport_num;
			delete filtered.transport_num;
		}
		return { ...skeleton, ...filtered };
	}

	// Función para mapear la factura existente a los formData
	function mapInvoiceToTopFields(invoice: any) {
		if (!invoice) return topFieldsSkeleton;

		let operationType: string | null = null;
		if (invoice.operation_type) {
			operationType = invoice.operation_type;
		} else if (data.filters?.operation_type !== undefined) {
			operationType = data.filters.operation_type ?? null;
		}

		return {
			is_pedimento_pending: invoice.compliance_mx?.is_pedimento_pending || false,
			pedimento_id: invoice.compliance_mx?.pedimento_id || '',
			remesa: invoice.compliance_mx?.remesa || '',
			invoice_number: invoice.invoice_number || '',
			invoice_date: invoice.invoice_date || new Date().toISOString().split('T')[0],
			emission_date: invoice.emission_date || new Date().toISOString().split('T')[0],
			operation_type: operationType,
			invoice_type: invoice.invoice_type || (data.filters?.invoice_type ?? ''),
			fecha_pedimento_del: '',
			fecha_pedimento_al: '',
			clave_pedimento: '',
			regimen_pedimento: ''
		};
	}

	function mapInvoiceToGeneral(invoice: any) {
		if (!invoice) return generalSkeleton;

		return {
			provider_header: invoice.compliance_mx?.provider_header || 'proveedor',
			provider_id: invoice.compliance_mx?.provider_id || null,
			sold_to_header: invoice.compliance_mx?.sold_to_header || 'consignado_a',
			sold_to_id: invoice.compliance_mx?.sold_to_id || null,
			shipped_to_header: invoice.compliance_mx?.shipped_to_header || 'enviado_a',
			shipped_to_id: invoice.compliance_mx?.shipped_to_id || null,
			customs_broker_id: invoice.compliance_mx?.customs_broker_id || null,
			customs_broker_us_id: invoice.compliance_mx?.customs_broker_us_id || null,
			currency_type: invoice.financials?.currency_type || '',
			currency: invoice.financials?.currency || 'foreign',
			exchange_rate: invoice.financials?.exchange_rate || null,
			weight_type: 'kgs',
			iva_factor: invoice.financials?.iva_factor || null,
			carrier_id: invoice.logistics?.carrier_id || null,
			transport_id: invoice.logistics?.transport_id || '',
			driver_name: invoice.logistics?.driver_name || '',
			transport_type: invoice.logistics?.transport_type || '',
			trailer_num: invoice.logistics?.trailer_num || '',
			aduana: invoice.compliance_mx?.aduana || '',
			document_type: invoice.document_type || ''
		};
	}

	function mapInvoiceToObservations(invoice: any) {
		if (!invoice) return observationSkeleton;

		return {
			observation_es: invoice.observation_es || '',
			observation_en: invoice.observation_en || '',
			freight: invoice.financials?.freight || null,
			insurance_value: invoice.financials?.insurance_value || null,
			insurance: invoice.financials?.insurance || null,
			packaging: invoice.financials?.packaging || null,
			other_increments: invoice.financials?.other_increments || null,
			total_increments_mn: invoice.financials?.total_increments_mn || null,
			total_increments_me: invoice.financials?.total_increments_me || null,
			incoterm: invoice.logistics?.incoterm || null,
			enclosure: invoice.compliance_mx?.enclosure || null,
			num_seals: null,
			movement_type: invoice.compliance_mx?.movement_type || '',
			alternate_invoice: invoice.alternate_invoice || '',
			valuation_method: invoice.compliance_mx?.value_method || null
		};
	}

	function mapInvoiceToItems(invoice: any) {
		if (!invoice) return ensureItemsFormData(null);

		return {
			items: invoice.items || []
		};
	}

	function mapInvoiceToOthers(invoice: any) {
		if (!invoice) return othersSkeleton;

		return {
			comments_status: invoice.comments_status || '',
			transport_mode: invoice.logistics?.transport_mode || 'TRUCK',
			is_mixed: invoice.compliance_mx?.is_mixed || false,
			print_stamp: invoice.print_stamp || false,
			rule_3121_parties_ii: invoice.compliance_mx?.rule_3121_parties_ii || false,
			related_doc_id: invoice.related_doc_id || null,
			code_signature: invoice.compliance_mx?.code_signature || '',
			electronic_signature: invoice.compliance_mx?.electronic_signature || '',
			mandatory_person: invoice.compliance_mx?.mandatory_person || '',
			contingency_mode: invoice.compliance_mx?.contingency_mode || false,
			cove: invoice.compliance_mx?.edocument || '',
			operation_num: invoice.compliance_mx?.vucem_operation_num || '',
			adendas: invoice.compliance_mx?.adendas || '',
			observations_vu: invoice.compliance_mx?.observations_vu || '',
			certified_number: invoice.compliance_mx?.certified_number || '',
			bill_number: invoice.logistics?.bill_number || '',
			guide_number: invoice.logistics?.guide_number || '',
			shipment_number: invoice.logistics?.shipment_number || '',
			option_iv18: invoice.compliance_mx?.option_iv18 || '',
			delivered_status: invoice.delivered_status || false,
			received_by: invoice.received_by || '',
			delivery_date: invoice.delivery_date || ''
		};
	}

	function mapInvoiceToContinuation(invoice: any) {
		if (!invoice) return continuationSkeleton;

		const logistics = invoice.logistics ?? {};
		const complianceMx = invoice.compliance_mx ?? {};

		return {
			numero_tipo_transporte:
				logistics.transport_num ?? logistics.vehicle_num ?? logistics.numero_tipo_transporte ?? '',
			es_ferrocarril:
				typeof logistics.is_rail === 'boolean'
					? logistics.is_rail
						? 'si'
						: 'no'
					: (logistics.es_ferrocarril ?? 'no'),
			numero_bl: logistics.bill_number ?? logistics.numero_bl ?? '',
			cantidad_guias_embarque: logistics.guide_number ?? logistics.cantidad_guias_embarque ?? null,
			destino_origen: logistics.destination_location ?? logistics.destino_origen ?? '',
			puerto_entrada: logistics.origin_location ?? logistics.puerto_entrada ?? '',
			vehicle_data: logistics.vehicle_data ?? '',
			fue_revisado_equipo: logistics.equipment_reviewed ?? logistics.fue_revisado_equipo ?? false,
			sub_division: logistics.is_subdivision ?? complianceMx.subdivision ?? false,
			funge_como_cd: logistics.acts_as_cd ?? false,
			llego_pedimento: logistics.pedimento_arrived ?? complianceMx.llego_pedimento ?? false,
			errores_facturacion: invoice.errores_facturacion || [],
			semaforo_verde_aduana_mexicana:
				logistics.green_light_mx ?? complianceMx.semaforo_verde_aduana_mexicana ?? false,
			semaforo_verde_aduana_americana:
				logistics.green_light_us ?? complianceMx.semaforo_verde_aduana_americana ?? false,
			semaforo_rojo_aduana_mexicana:
				logistics.red_light_mx ?? complianceMx.semaforo_rojo_aduana_mexicana ?? false,
			semaforo_rojo_aduana_americana:
				logistics.red_light_us ?? complianceMx.semaforo_rojo_aduana_americana ?? false,
			is_mixed: complianceMx.is_mixed ?? false,
			reason_export: complianceMx.reason_export ?? '1',
			purchase_order: invoice.purchase_order || '',
			payment_terms: invoice.payment_terms || '',
			handling_fees: invoice.financials?.handling_fees || 0,
			cfdi_uuid: invoice.cfdi_uuid || '',
			path_pdf: invoice.path_pdf || '',
			path_xml: invoice.path_xml || ''
		};
	}

	// Resolved defaults logic: check both ssisgen and qsisgen keys in the nested settings
	const resolvedDefaults = $derived.by(() => {
		// FIX: data.defaultSettings is already the settings object for this specific type
		const settings = data.defaultSettings || {};
		const ssisgen = settings.ssisgen || {};
		const qsisgen = settings.qsisgen || {};
		return { ...qsisgen, ...ssisgen };
	});

	// Referencias a los componentes de formulario para obtener sus datos
	// Si estamos en modo edición (!data.isCreate) y tenemos una factura, usarla
	// Si estamos en modo creación, usar resolvedDefaults
	let InvoiceTopFieldsFormData = $state<any>(
		!data.isCreate && data.invoice
			? mapInvoiceToTopFields(data.invoice)
			: mergeDefaults(topFieldsSkeleton, resolvedDefaults.InvoiceTopFieldsFormData)
	);
	let generalFormData = $state<any>(
		!data.isCreate && data.invoice
			? mapInvoiceToGeneral(data.invoice)
			: mergeDefaults(generalSkeleton, resolvedDefaults.generalFormData)
	);
	let observationFormData = $state<any>(
		!data.isCreate && data.invoice
			? mapInvoiceToObservations(data.invoice)
			: mergeDefaults(observationSkeleton, resolvedDefaults.observationFormData)
	);
	let itemsFormData = $state<any>(
		!data.isCreate && data.invoice
			? mapInvoiceToItems(data.invoice)
			: ensureItemsFormData(resolvedDefaults.itemsFormData)
	);
	let othersFormData = $state<any>(
		!data.isCreate && data.invoice
			? mapInvoiceToOthers(data.invoice)
			: mergeDefaults(othersSkeleton, resolvedDefaults.othersFormData)
	);
	let continuationFormData = $state<any>(
		!data.isCreate && data.invoice
			? mapInvoiceToContinuation(data.invoice)
			: mergeDefaults(continuationSkeleton, resolvedDefaults.continuationFormData)
	);

	// Estados para saber si existen datos previos
	let observationExists = $state(
		!data.isCreate ? !!data.invoice : !!resolvedDefaults.observationFormData
	);
	let itemsExists = $state(
		!data.isCreate
			? !!(data.invoice?.items && data.invoice.items.length > 0)
			: !!resolvedDefaults.itemsFormData?.items?.length
	);
	let othersExists = $state(
		!data.isCreate ? !!data.invoice : !!resolvedDefaults.othersFormData
	);
	let continuationExists = $state(
		!data.isCreate ? !!data.invoice : !!resolvedDefaults.continuationFormData
	);

	let calculatedExchangeRate = $state<number | null>(
		data.invoice?.financials?.exchange_rate ?? null
	);

	let showExchangeRateDialog = $state(false);

	$effect(() => {
		if (showExchangeRateDialog) {
			uiStore.isExchangeRateDialogOpen = true;
		} else {
			// Solo limpiar si este componente tenía el modal abierto
			if (uiStore.isExchangeRateDialogOpen && !showExchangeRateDialog) {
				uiStore.isExchangeRateDialogOpen = false;
			}
		}
	});

	let missingExchangeRateDate = $state('');
	let lastFetchedDate = $state('');
	let originalInvoiceDate = $state(data.invoice?.invoice_date || '');

	// Tipo de factura efectivo (cabecera + tabs): prioridad campos superiores, luego URL/factura.
	// En importación sin tipo aún, se asume TEM como antes; en exportación sin tipo, cadena vacía (sin forzar TEM).
	let invoiceType = $derived.by(() => {
		const top = InvoiceTopFieldsFormData?.invoice_type;
		if (top !== undefined && top !== null && String(top).trim() !== '') {
			return String(top).trim();
		}
		if (data.filters?.invoice_type) return String(data.filters.invoice_type).trim();
		if (data.invoice?.invoice_type) return String(data.invoice.invoice_type).trim();
		const op =
			InvoiceTopFieldsFormData?.operation_type ||
			data.invoice?.operation_type ||
			data.filters?.operation_type;
		return op === 'imp' ? 'TEM' : '';
	});

	let operationTypeText = $derived.by(() => {
		const type =
			InvoiceTopFieldsFormData?.operation_type ||
			data.invoice?.operation_type ||
			data.filters?.operation_type;
		if (invoiceType === 'CR') return 'CAMBIO DE RÉGIMEN';
		if (type === 'exp') return 'EXPORTACIÓN';
		if (type === 'imp') return 'IMPORTACIÓN';
		return 'TIPO NO DEFINIDO';
	});

	let operationColorClass = $derived.by(() => {
		const type =
			InvoiceTopFieldsFormData?.operation_type ||
			data.invoice?.operation_type ||
			data.filters?.operation_type;
		if (type === 'exp') return 'bg-blue-500/10 text-blue-600 border-blue-500/20';
		if (type === 'imp') return 'bg-emerald-500/10 text-emerald-600 border-emerald-500/20';
		return 'bg-muted text-muted-foreground border-border';
	});

	// Pedimentos filtrados por tipo de operación: vacío → todos; imp/exp → solo los que coinciden
	let filteredPedimentos = $derived.by(() => {
		const list = data.pedimentos || [];
		const opType =
			InvoiceTopFieldsFormData?.operation_type ||
			data.invoice?.operation_type ||
			data.filters?.operation_type;
		if (!opType || opType === '') return list;
		return list.filter((p: { operation_type?: string }) => p.operation_type === opType);
	});

	let lastInheritancePedimentoId: number | null = null;
	let hasInitializedInheritanceState = false;

	// Al seleccionar pedimento, autollenar Aduana y Clave de régimen (document_type)
	// Fuente de verdad: pedimento.customs_office (aduana) y pedimento.regime (régimen)
	$effect(() => {
		const pid = InvoiceTopFieldsFormData?.pedimento_id;
		const currentPedimentoId =
			typeof pid === 'string'
				? (Number.parseInt(pid, 10) || null)
				: (pid ?? null);

		// Edición: solo reaplicar en transición real a nuevo pedimento.
		// No sobrescribir/borrar al abrir la pantalla ni en cambios no relacionados.
		if (!data.isCreate) {
			if (!hasInitializedInheritanceState) {
				lastInheritancePedimentoId = currentPedimentoId;
				hasInitializedInheritanceState = true;
				return;
			}

			const pedimentoChanged = lastInheritancePedimentoId !== currentPedimentoId;
			const hasPedimentoNow = !!currentPedimentoId;
			const shouldReapplyFromPedimento = pedimentoChanged && hasPedimentoNow;

			lastInheritancePedimentoId = currentPedimentoId;

			if (!shouldReapplyFromPedimento || !generalFormData) return;

			const ped = (data.pedimentos || []).find((p: any) => p?.id === currentPedimentoId);
			if (!ped) return;

			// En edición, cuando hay transición válida, pedimento manda (incluyendo vacío).
			generalFormData.aduana = ped.customs_office || '';
			generalFormData.document_type = ped.regime || '';
			return;
		}

		// Si se marca pedimento pendiente, el componente ya limpia pedimento/remesa;
		// aquí limpiamos también los campos que dependen del pedimento.
		if (InvoiceTopFieldsFormData?.is_pedimento_pending) {
			if (generalFormData) {
				generalFormData.aduana = '';
				generalFormData.document_type = '';
			}
			return;
		}

		if (!pid || !generalFormData) return;
		const id = typeof pid === 'string' ? Number.parseInt(pid, 10) : pid;
		if (!id || Number.isNaN(id)) return;

		const ped = (filteredPedimentos || []).find((p: any) => p?.id === id);
		if (!ped) return;

		// Solo autollenar si están vacíos (no pisar captura manual)
		if (!generalFormData.aduana && ped.customs_office) {
			generalFormData.aduana = ped.customs_office;
		}
		if (!generalFormData.document_type && ped.regime) {
			generalFormData.document_type = ped.regime;
		}
	});

	let remesaSuggestionReqId = 0;
	let lastRemesaPedimentoId: number | null = null;
	let lastAutoSuggestedRemesa: string | null = null;
	$effect(() => {
		if (InvoiceTopFieldsFormData?.is_pedimento_pending) return;

		const companyId = companyStore?.activeCompany?.id;
		const pid = InvoiceTopFieldsFormData?.pedimento_id;
		if (!companyId || !pid) {
			lastRemesaPedimentoId = null;
			lastAutoSuggestedRemesa = null;
			return;
		}

		const pedimentoId = typeof pid === 'string' ? parseInt(pid, 10) : pid;
		if (!pedimentoId || Number.isNaN(pedimentoId)) return;

		const currentRemesa = String(InvoiceTopFieldsFormData?.remesa || '');
		const isCurrentRemesaAuto = lastAutoSuggestedRemesa != null && currentRemesa === lastAutoSuggestedRemesa;

		// Si cambió el pedimento, solo recalcular si la remesa está vacía
		// (o si la remesa actual fue auto-sugerida previamente)
		if (lastRemesaPedimentoId !== pedimentoId) {
			lastRemesaPedimentoId = pedimentoId;
			if (!currentRemesa || isCurrentRemesaAuto) {
				InvoiceTopFieldsFormData.remesa = '';
				lastAutoSuggestedRemesa = null;
			} else {
				// Remesa ya capturada / existente: no sobrescribir
				return;
			}
		} else {
			// Mismo pedimento: solo sugerir si está vacía
			if (currentRemesa) return;
		}

		const myReq = ++remesaSuggestionReqId;
		(async () => {
			try {
				const op =
					InvoiceTopFieldsFormData?.operation_type ||
					data.invoice?.operation_type ||
					data.filters?.operation_type;
				const inv =
					InvoiceTopFieldsFormData?.invoice_type ||
					data.invoice?.invoice_type ||
					data.filters?.invoice_type;
				let remesaUrl = `/v1/a76/invoices/remesa-suggestion?company_id=${companyId}&pedimento_id=${pedimentoId}`;
				if (op) remesaUrl += `&operation_type=${encodeURIComponent(String(op))}`;
				if (inv) remesaUrl += `&invoice_type=${encodeURIComponent(String(inv))}`;
				const res = await api.get(remesaUrl);
				if (myReq !== remesaSuggestionReqId) return;
				const next = (res as any)?.data?.next_remesa;
				if (typeof next === 'number' && next > 0) {
					const nextStr = String(next);
					InvoiceTopFieldsFormData.remesa = nextStr;
					lastAutoSuggestedRemesa = nextStr;
				}
			} catch (e) {
				// Silencioso: no bloquear selección de pedimento por fallo de sugerencia
			}
		})();
	});

	async function checkExchangeRate(date: string): Promise<boolean> {
		if (!date || !companyStore?.activeCompany?.id) return true;

		// Si ya tenemos un tipo de cambio calculado y es válido, asumimos que existe
		if (calculatedExchangeRate && calculatedExchangeRate > 0) return true;

		try {
			// Verificar explícitamente si existe
			const response = await getExchangeRates(companyStore.activeCompany.id, {
				date: date,
				page_size: 1
			});

			const actualResponse = response as any;
			const items = actualResponse.data?.items || [];

			if (items.length === 0) {
				if (!uiStore.isExchangeRateDialogOpen) {
					missingExchangeRateDate = date;
					showExchangeRateDialog = true;
					uiStore.isExchangeRateDialogOpen = true;
					return false;
				}
				// Si ya hay un modal abierto, no abrir este pero retornar false para indicar que falta
				return false;
			}
			return true;
		} catch (error) {
			console.error('Error checking exchange rate:', error);
			// Ante la duda, si es un error de red, quizás deberíamos dejar pasar o bloquear.
			// Si asumimos que falló la petición, mejor pedir al usuario que verifique.
			// O podríamos asumir que falta si es 404/Empty.
			// Por seguridad, abrimos modal.
			missingExchangeRateDate = date;
			showExchangeRateDialog = true;
			return false;
		}
	}

	// Efecto para actualizar el tipo de cambio cuando cambia la fecha de factura
	$effect(() => {
		const currentDate = InvoiceTopFieldsFormData?.invoice_date;

		if (mounted && companyStore?.activeCompany?.id && currentDate) {
			// No buscar si:
			// 1. Ya tenemos un valor y la fecha es la original (evita sobreescribir al cargar)
			const currentRate = calculatedExchangeRate;
			if (
				!data.isCreate &&
				currentDate === originalInvoiceDate &&
				typeof currentRate === 'number' &&
				currentRate > 0
			) {
				return;
			}

			// 2. Ya buscamos para esta fecha recientemente
			if (currentDate === lastFetchedDate) {
				return;
			}

			getExchangeRateByDate(currentDate, companyStore.activeCompany.id)
				.then((rate) => {
					lastFetchedDate = currentDate;
					if (rate) {
						calculatedExchangeRate = rate.value;
					} else {
						calculatedExchangeRate = 0;
						// Solo abrir modal si NO es la fecha de hoy (el guard global la maneja)
						// Y si no hay otro modal de TC abierto ya
						const today = new Date().toISOString().split('T')[0];
						if (currentDate !== today && !uiStore.isExchangeRateDialogOpen) {
							missingExchangeRateDate = currentDate;
							showExchangeRateDialog = true;
							uiStore.isExchangeRateDialogOpen = true;
						}
					}
				})
				.catch((err) => console.error('Error auto-updating exchange rate:', err));
		}
	});

	function invoicesListPath(): string {
		const searchParams = new URLSearchParams($page.url.search);
		
		// Si no hay parámetros en la URL (ej. recarga de página), intentamos reconstruirlos del estado
		if (!searchParams.has('operation_type')) {
			const opType = InvoiceTopFieldsFormData?.operation_type || data.invoice?.operation_type || data.filters?.operation_type;
			if (opType) searchParams.set('operation_type', opType);
		}
		
		if (!searchParams.has('invoice_type')) {
			const invType = InvoiceTopFieldsFormData?.invoice_type || data.invoice?.invoice_type || data.filters?.invoice_type;
			if (invType) searchParams.set('invoice_type', invType);
		}

		const qs = searchParams.toString();
		return qs ? `/dashboard/invoices?${qs}` : '/dashboard/invoices';
	}

	function handleBack() {
		goto(invoicesListPath());
	}

	function getOperationColor(type?: string | null): 'default' | 'secondary' {
		if (!type) return 'secondary';
		return type === 'imp' ? 'default' : 'secondary';
	}

	async function handleSaveAll() {
		saving = true;
		validationHighlightField = null;

		try {
			// Validar ID si es edición
			if (!data.isCreate && !invoiceId) {
				toast.error(m.invoice_edit_page_save_error_prefix(), {
					description: 'Error interrrno: No se encuentra el ID de la factura para actualizar.'
				});
				saving = false;
				return;
			}

			// Verificar tipo de cambio antes de guardar
			if (InvoiceTopFieldsFormData?.invoice_date) {
				const rateExists = await checkExchangeRate(InvoiceTopFieldsFormData.invoice_date);
				if (!rateExists) {
					saving = false;
					return;
				}
			}

			const result = await saveInvoice({
				invoiceId,
				isCreate: data.isCreate || false,
				companyId: companyStore?.activeCompany?.id || 0,
				formData: {
					InvoiceTopFieldsFormData: $state.snapshot(InvoiceTopFieldsFormData),
					generalFormData: $state.snapshot(generalFormData),
					observationFormData: $state.snapshot(observationFormData),
					itemsFormData: $state.snapshot(itemsFormData),
					othersFormData: $state.snapshot(othersFormData),
					continuationFormData: $state.snapshot(continuationFormData)
				}
			});

			if (!result.success) {
				const field =
					result.firstInvalidField ||
					(result.validationErrors?.[0]?.field
						? normalizeInvoiceFieldPath(result.validationErrors[0].field)
						: undefined);
				if (field) {
					validationHighlightField = field;
					await focusInvoiceInvalidField((t) => (activeTab = t), field);
				}
				const error: any = new Error(result.error || 'Error al guardar la factura');
				if (result.validationErrors) {
					error.validationErrors = result.validationErrors;
				}
				throw error;
			}

			validationHighlightField = null;
			toast.success(m.invoice_edit_saved_success());
			
			// Si fue una creación exitosa, actualizar el ID local inmediatamente
			if (result.newInvoiceId) {
				invoiceId = result.newInvoiceId;
			}
		} catch (e: any) {
			console.error('Error saving all:', e);

			// Handle 401 Unauthorized specifically for session expiration
			if (e.response?.status === 401 || (e instanceof Error && e.message.includes('401'))) {
				toast.error(m.invoice_edit_page_session_expired());
				setTimeout(() => {
					window.location.reload();
				}, 1500);
				return; // Exit early after handling 401
			}

			// Intercept exchange rate error
			if (
				e.response?.data?.message?.includes('No existe un Tipo de Cambio registrado') ||
				e.message?.includes('No existe un Tipo de Cambio registrado') ||
				e.response?.data?.errors?.[0]?.message?.includes('financials.exchange_rate')
			) {
				console.log('Interceptor: Exchange rate missing error caught (Invoice Page).');

				const dateMatch =
					e.response?.data?.message?.match(/(\d{4}-\d{2}-\d{2})/) ||
					e.message?.match(/(\d{4}-\d{2}-\d{2})/);
				const missingDate = dateMatch ? dateMatch[0] : InvoiceTopFieldsFormData?.invoice_date || '';

				missingExchangeRateDate = missingDate;
				showExchangeRateDialog = true;
				saving = false; // Ensure saving state is reset
				return; // Exit early after handling exchange rate error
			}

			// General error handling with detailed backend messages
			const detail = e.response?.data?.errors?.[0]?.message;
			const mainMsg = e.response?.data?.message || e.message || m.invoice_edit_page_save_error_prefix();

			// If there are validation errors, show them in detail
			if (
				e &&
				typeof e === 'object' &&
				'validationErrors' in e &&
				Array.isArray((e as any).validationErrors)
			) {
				const validationErrors = (e as any).validationErrors;
				const errorList = validationErrors.map((err: any) => `• ${err.message}`).join('\n');
				toast.error(mainMsg, {
					description: errorList
				});
			} else {
				const errorMessage = e instanceof Error ? e.message : m.invoice_edit_page_save_changes_error();

				// Intercept exchange rate error
				if (
					errorMessage.includes('No existe un Tipo de Cambio registrado') ||
					errorMessage.includes('financials.exchange_rate')
				) {
					console.log('Interceptor: Exchange rate missing error caught (Invoice Page).');

					const dateMatch = errorMessage.match(/(\d{4}-\d{2}-\d{2})/);
					const missingDate = dateMatch
						? dateMatch[0]
						: InvoiceTopFieldsFormData?.invoice_date || '';

					missingExchangeRateDate = missingDate;
					showExchangeRateDialog = true;
					return;
				}

				// Si hay errores de validación, mostrarlos en detalle
				if (
					e &&
					typeof e === 'object' &&
					'validationErrors' in e &&
					Array.isArray((e as any).validationErrors)
				) {
					const validationErrors = (e as any).validationErrors;
					const errorList = validationErrors.map((err: any) => `• ${err.message}`).join('\n');

					toast.error(errorMessage, {
						description: errorList
					});
				} else {
					toast.error(errorMessage, {
						description: m.invoice_edit_page_console_hint()
					});
				}
			}
		} finally {
			saving = false;
		}
	}

	let isLoadingDefaults = $state(false);

	// Compute initial key from source data to avoid state reference warning
	const initialLoadedKey = data.defaultSettings?.InvoiceTopFieldsFormData
		? `${data.defaultSettings.InvoiceTopFieldsFormData.invoice_type || ''}-${data.defaultSettings.InvoiceTopFieldsFormData.operation_type || ''}`
		: '';
	let lastLoadedKey = $state(initialLoadedKey);

	// Create a derived value for the current key to track changes reactively
	let currentKey = $derived(
		InvoiceTopFieldsFormData?.invoice_type && InvoiceTopFieldsFormData?.operation_type
			? `${InvoiceTopFieldsFormData.invoice_type}-${InvoiceTopFieldsFormData.operation_type}`
			: ''
	);

	async function loadDefaults() {
		if (
			!data.isCreate ||
			!InvoiceTopFieldsFormData.invoice_type ||
			!InvoiceTopFieldsFormData.operation_type ||
			!companyStore?.activeCompany?.id
		)
			return;

		if (currentKey === lastLoadedKey) return;

		isLoadingDefaults = true;
		try {
			const res = await api.get(
				`/v1/a76/invoice-settings/${InvoiceTopFieldsFormData.invoice_type}?operation_type=${InvoiceTopFieldsFormData.operation_type}&company_id=${companyStore.activeCompany.id}`
			);

			if (!res.error && res.data) {
				const settings = res.data.settings || {};
				const ssisgen = settings.ssisgen || {};
				const qsisgen = settings.qsisgen || {};
				const combined = { ...qsisgen, ...ssisgen };

				// Mark as loaded even if empty to prevent retries for the same combination
				lastLoadedKey = currentKey;

				// Only notify and apply if there are actually settings
				if (Object.keys(settings).length === 0) return;

				// Re-apply merges with new defaults
				InvoiceTopFieldsFormData = mergeDefaults(
					topFieldsSkeleton,
					combined.InvoiceTopFieldsFormData
				);
				generalFormData = mergeDefaults(generalSkeleton, combined.generalFormData);
				observationFormData = mergeDefaults(observationSkeleton, combined.observationFormData);
				itemsFormData = ensureItemsFormData(combined.itemsFormData);
				othersFormData = mergeDefaults(othersSkeleton, combined.othersFormData);
				continuationFormData = mergeDefaults(continuationSkeleton, combined.continuationFormData);

				// Ensure types remain as selected
				InvoiceTopFieldsFormData.invoice_type =
					InvoiceTopFieldsFormData.invoice_type || data.filters?.invoice_type;
				InvoiceTopFieldsFormData.operation_type =
					InvoiceTopFieldsFormData.operation_type || data.filters?.operation_type;

				observationExists = !!settings.observationFormData;
				itemsExists = !!itemsFormData.items?.length;
				othersExists = !!settings.othersFormData;
				continuationExists = !!settings.continuationFormData;

				toast.info(
					`${m.invoice_edit_form_loading_defaults_prefix()} ${InvoiceTopFieldsFormData.invoice_type}`
				);
			}
		} catch (error) {
			console.error('Error loading defaults:', error);
		} finally {
			isLoadingDefaults = false;
		}
	}

	// Dynamic defaults loading when types change in "New" mode
	$effect(() => {
		if (
			data.isCreate &&
			mounted &&
			companyStore?.activeCompany?.id &&
			InvoiceTopFieldsFormData.invoice_type &&
			InvoiceTopFieldsFormData.operation_type
		) {
			// Trigger only if types actually changed from initial load or previous selection
			loadDefaults();
		}
	});

	useShortcuts(
		'Invoice Edit',
		obtenerAtajosEdicionFactura({
			cambiarPestana: (pestana) => (activeTab = pestana),
			manejarGuardar: handleSaveAll,
			manejarRegresar: handleBack
		})
	);

	// Prerrequisitos: modal cuando no hay agentes o clientes
	const agentsCount = $derived(data.customsBrokers?.length ?? 0);
	const clientsCount = $derived(data.clients?.length ?? 0);
	let showPrerequisitesModal = $state(false);
	let hasTriedToShowPrerequisitesModal = $state(false);
	$effect(() => {
		if (hasTriedToShowPrerequisitesModal) return;
		if (agentsCount === 0 || clientsCount === 0) {
			hasTriedToShowPrerequisitesModal = true;
			showPrerequisitesModal = true;
		}
	});
</script>

<div class="space-y-3">
	<!-- Header -->
	<div class="flex items-center justify-between">
		<div class="space-y-1">
			<div class="flex items-center gap-3">
				<Button variant="ghost" size="icon" onclick={handleBack}>
					<ArrowLeft size={20} />
				</Button>
				<h1 class="text-3xl font-bold tracking-tight">
					{#if data.isCreate}
						{m.invoice_edit_new_title()}
					{:else}
						{m.invoice_edit_page_invoice_prefix()}{data.invoice.id}
					{/if}
					{#if invoiceType}
						{@const headerInvoiceTypeInfo = data.invoiceTypes?.find((t) => t.key === invoiceType)}
						{#if headerInvoiceTypeInfo}
							<span class="text-2xl font-normal text-muted-foreground">
								- {headerInvoiceTypeInfo.description}
							</span>
						{/if}
					{/if}
				</h1>
				<Badge variant="outline" class="px-3 py-1 text-sm font-bold {operationColorClass}">
					{operationTypeText}
				</Badge>
				{#if data.isCreate}
					<Badge variant="secondary">{m.invoice_edit_draft_badge()}</Badge>
				{/if}
			</div>
			<p class="text-muted-foreground">
				{#if !data.isCreate && data.invoice.invoice_number}
					{m.invoice_edit_invoice_number_prefix()} {data.invoice.invoice_number}
				{:else}
					{m.invoice_edit_edit_details()}
				{/if}
			</p>
		</div>
	</div>

	<Separator />

	<!-- Contenido de las tabs con padding inferior para el footer flotante -->
	<div class="pb-48">
		<Tabs.Root bind:value={activeTab}>
			<InvoiceTopFields
				invoice={data.invoice}
				bind:formData={InvoiceTopFieldsFormData}
				invoiceTypes={data.invoiceTypes || []}
				pedimentos={filteredPedimentos}
				defaultOperationType={data.filters?.operation_type ?? undefined}
				defaultInvoiceType={data.filters?.invoice_type ?? undefined}
				{invoiceType}
				isCreate={data.isCreate === true}
				highlightFieldId={validationHighlightField}
				onDismissHighlightForField={dismissValidationHighlight}
			/>

			<Tabs.Content value="general">
				<GeneralTabForm
					invoice={data.invoice}
					bind:formData={generalFormData}
					invoiceTypes={data.invoiceTypes || []}
					{invoiceType}
					customsBrokers={data.customsBrokers || []}
					clients={data.clients || []}
					providers={data.providers || []}
					currencyTypes={data.currencyTypes || []}
					transportTypes={data.transportTypes || []}
					transporters={data.transporters || []}
					vehicles={data.vehicles || []}
					drivers={data.drivers || []}
					trailers={data.trailers || []}
					customsSections={data.customsSections || []}
					codePedimentoRegimens={data.codePedimentoRegimens || []}
					defaultOperationType={data.filters?.operation_type ?? undefined}
					defaultInvoiceType={data.filters?.invoice_type ?? undefined}
					operationType={InvoiceTopFieldsFormData?.operation_type === 'exp'
						? 1
						: InvoiceTopFieldsFormData?.operation_type === 'imp'
							? 2
							: data.invoice?.operation_type === 'exp'
								? 1
								: data.invoice?.operation_type === 'imp'
									? 2
									: undefined}
					exchangeRate={calculatedExchangeRate}
					highlightFieldId={validationHighlightField}
					onDismissHighlightForField={dismissValidationHighlight}
				/>
			</Tabs.Content>

			<Tabs.Content value="observations">
				<ObservationsTabForm
					invoice={data.invoice}
					bind:formData={observationFormData}
					bind:exists={observationExists}
					seals={data.seals || []}
					incoterms={data.incoterms || []}
					valuationMethods={data.valuationMethods || []}
					enclosure={data.enclosure || []}
					legends={data.legends || []}
					{invoiceType}
					operationType={InvoiceTopFieldsFormData?.operation_type === 'exp'
						? 1
						: InvoiceTopFieldsFormData?.operation_type === 'imp'
							? 2
							: data.invoice?.operation_type === 'exp'
								? 1
								: data.invoice?.operation_type === 'imp'
									? 2
									: undefined}
					highlightFieldId={validationHighlightField}
					onDismissHighlightForField={dismissValidationHighlight}
				/>
			</Tabs.Content>

			<Tabs.Content value="items">
				<ItemsTabForm
					invoice={data.invoice}
					bind:formData={itemsFormData}
					bind:exists={itemsExists}
					highlightFieldId={validationHighlightField}
					onDismissHighlightForField={dismissValidationHighlight}
					{invoiceType}
					operationType={InvoiceTopFieldsFormData?.operation_type === 'exp'
						? 1
						: InvoiceTopFieldsFormData?.operation_type === 'imp'
							? 2
							: data.invoice?.operation_type === 'exp'
								? 1
								: data.invoice?.operation_type === 'imp'
									? 2
									: undefined}
				/>
			</Tabs.Content>

			<Tabs.Content value="others">
				<OthersTabForm
					invoice={data.invoice}
					bind:formData={othersFormData}
					bind:exists={othersExists}
					{invoiceType}
					operationType={InvoiceTopFieldsFormData?.operation_type === 'exp'
						? 1
						: InvoiceTopFieldsFormData?.operation_type === 'imp'
							? 2
							: data.invoice?.operation_type === 'exp'
								? 1
								: data.invoice?.operation_type === 'imp'
									? 2
									: undefined}
					transportModes={data.transportModes || []}
				/>
			</Tabs.Content>

			{#if invoiceType !== 'MEX'}
				<Tabs.Content value="continuation">
					<ContinuationTabForm
						invoice={data.invoice}
						bind:formData={continuationFormData}
						bind:exists={continuationExists}
						{invoiceType}
						operationType={InvoiceTopFieldsFormData?.operation_type === 'exp'
							? 1
							: InvoiceTopFieldsFormData?.operation_type === 'imp'
								? 2
								: data.invoice?.operation_type === 'exp'
									? 1
									: data.invoice?.operation_type === 'imp'
										? 2
										: undefined}
					/>
				</Tabs.Content>
			{/if}
		</Tabs.Root>
	</div>
</div>

<!-- Footer fijo en la parte inferior -->
<ExchangeRateDialog
	bind:open={showExchangeRateDialog}
	initialDate={missingExchangeRateDate}
	overlayClass="bg-black/5"
	onSuccess={() => {
		uiStore.isExchangeRateDialogOpen = false;
		// Si es factura nueva y no tiene fecha, poner la de hoy
		if (data.isCreate && !InvoiceTopFieldsFormData.invoice_date) {
			InvoiceTopFieldsFormData.invoice_date = new Date().toISOString().split('T')[0];
		}

		// Actualizar el tipo de cambio mostrado
		if (InvoiceTopFieldsFormData.invoice_date && companyStore?.activeCompany?.id) {
			getExchangeRateByDate(
				InvoiceTopFieldsFormData.invoice_date,
				companyStore.activeCompany.id
			).then((rate) => {
				if (rate) calculatedExchangeRate = rate.value;
			});
		}
	}}
/>
<div
	class="fixed right-0 bottom-0 left-0 z-[5] md:ml-[calc(var(--sidebar-width))] border-t bg-background/95 shadow-lg backdrop-blur md:group-has-data-[state=collapsed]/sidebar-wrapper:ml-[calc(var(--sidebar-width-icon))] supports-[backdrop-filter]:bg-background/80"
>
	<div class="mx-auto max-w-[1400px] space-y-4 px-4 py-4">
		<!-- Tabs Navigation -->
		<Tabs.Root bind:value={activeTab}>
			<div class="w-full overflow-x-auto pb-2">
				<Tabs.List
					class="inline-flex md:grid md:w-full {invoiceType === 'MEX'
						? 'md:grid-cols-4'
						: 'md:grid-cols-5'}"
				>
					<Tabs.Trigger value="general" disabled={false} class="whitespace-nowrap">
						<FileText size={16} class="mr-2" />
						{m.invoice_edit_tabs_general()}
					</Tabs.Trigger>
					<Tabs.Trigger value="observations" disabled={false} class="whitespace-nowrap">
						<Eye size={16} class="mr-2" />
						{m.invoice_edit_tabs_observations()}
					</Tabs.Trigger>
					<Tabs.Trigger value="items" disabled={false} class="whitespace-nowrap">
						<DollarSign size={16} class="mr-2" />
						{m.invoice_edit_tabs_items()}
					</Tabs.Trigger>
					<Tabs.Trigger value="others" disabled={false} class="whitespace-nowrap">
						<Truck size={16} class="mr-2" />
						{m.invoice_edit_tabs_others()}
					</Tabs.Trigger>
					{#if invoiceType !== 'MEX'}
						<Tabs.Trigger value="continuation" disabled={false} class="whitespace-nowrap">
							<Package size={16} class="mr-2" />
							{m.invoice_edit_tabs_continuation()}
						</Tabs.Trigger>
					{/if}
				</Tabs.List>
			</div>
		</Tabs.Root>

		<!-- Botones de acción -->
		<div class="flex justify-end gap-3">
			<Button type="button" variant="outline" onclick={handleBack} disabled={saving}>
				{m.invoice_edit_page_cancel()}
			</Button>
			<Button onclick={handleSaveAll} disabled={saving}>
				{#if saving}
					<LoaderCircle class="mr-2 h-4 w-4 animate-spin" />
					{m.invoice_edit_page_saving_all_changes()}
				{:else}
					<Save size={16} class="mr-2" />
					{m.invoice_edit_page_save_all_changes()}
				{/if}
			</Button>
		</div>
	</div>
</div>

<PrerequisitesModal
	bind:open={showPrerequisitesModal}
	{agentsCount}
	{clientsCount}
	onAccept={() => (showPrerequisitesModal = false)}
	onCancel={() => goto(invoicesListPath())}
/>
