import { goto } from '$app/navigation';
import { invoicesApi, type CreateInvoiceData, type UpdateInvoiceData } from '$lib/api/dashboard/a76/invoices';
import { m } from '$lib/i18n/messages';
import { normalizeInvoiceFieldPath } from './focus-invoice-field';

interface FormDataSet {
	InvoiceTopFieldsFormData: any;
	generalFormData: any;
	observationFormData: any;
	itemsFormData: any;
	othersFormData: any;
	continuationFormData: any;
}

interface SaveInvoiceOptions {
	invoiceId: number | null;
	isCreate: boolean;
	companyId: number;
	formData: FormDataSet;
}

interface SaveInvoiceResult {
	success: boolean;
	error?: string;
	newInvoiceId?: number;
	/** Normalized field key for focus/highlight (see focus-invoice-field.ts). */
	firstInvalidField?: string;
	validationErrors?: Array<{
		field: string;
		message: string;
		code?: string;
		solution?: string[];
		value?: any;
	}>;
}

function _logisticsStrNonempty(value: unknown): boolean {
	return value != null && String(value).trim() !== '';
}

/** Remolque obligatorio si tipo != none (mismo criterio que validate_common). */
function validateClientLogistics(formData: FormDataSet): SaveInvoiceResult['validationErrors'] {
	const g = formData.generalFormData;
	const transportType = _logisticsStrNonempty(g?.transport_type) ? String(g.transport_type).trim() : 'none';
	if (transportType === 'none' || _logisticsStrNonempty(g?.trailer_num)) {
		return undefined;
	}
	return [
		{
			field: 'logistics.trailer_num',
			message: m.invoice_edit_form_validation_trailer_required(),
			code: 'REQUIRED_FIELD',
			value: g?.trailer_num
		}
	];
}

export async function saveInvoice(options: SaveInvoiceOptions): Promise<SaveInvoiceResult> {
	const { invoiceId, isCreate, companyId, formData } = options;
	const { InvoiceTopFieldsFormData, generalFormData, observationFormData, itemsFormData, othersFormData, continuationFormData } = formData;

	try {
		// Validar campos requeridos para creación (orden = primer campo inválido)
		if (isCreate) {
			const requiredFields = {
				operation_type: m.invoice_edit_form_operation_type_label(),
				invoice_type: m.invoice_edit_form_invoice_type_label(),
				invoice_number: m.invoice_edit_form_invoice_number_label(),
				document_type: m.invoice_edit_general_document_type_label()
			};

			if (!InvoiceTopFieldsFormData?.operation_type) {
				return {
					success: false,
					error: `${m.invoice_edit_form_validation_missing_fields()} ${requiredFields.operation_type}`,
					firstInvalidField: 'operation_type'
				};
			}
			if (!InvoiceTopFieldsFormData?.invoice_type) {
				return {
					success: false,
					error: `${m.invoice_edit_form_validation_missing_fields()} ${requiredFields.invoice_type}`,
					firstInvalidField: 'invoice_type'
				};
			}
			if (!InvoiceTopFieldsFormData?.invoice_number) {
				return {
					success: false,
					error: `${m.invoice_edit_form_validation_missing_fields()} ${requiredFields.invoice_number}`,
					firstInvalidField: 'invoice_number'
				};
			}
			if (!generalFormData?.document_type && InvoiceTopFieldsFormData?.invoice_type !== 'MEX') {
				return {
					success: false,
					error: `${m.invoice_edit_form_validation_missing_fields()} ${requiredFields.document_type}`,
					firstInvalidField: 'document_type'
				};
			}
		}

		// Validar Aduana para cualquier tipo de guardado si no es MEX
		if (!generalFormData?.aduana && InvoiceTopFieldsFormData?.invoice_type !== 'MEX') {
			return {
				success: false,
				error: `${m.invoice_edit_form_validation_missing_fields()} ${m.invoice_edit_general_customs_label()}`,
				firstInvalidField: 'aduana'
			};
		}

		const logisticsErrors = validateClientLogistics(formData);
		if (logisticsErrors?.length) {
			return {
				success: false,
				error: m.invoice_edit_form_validation_check_transport_data(),
				validationErrors: logisticsErrors,
				firstInvalidField: normalizeInvoiceFieldPath(logisticsErrors[0]?.field)
			};
		}

		// Construir el payload unificado
		const payload = buildInvoicePayload(formData);

		let newInvoiceId = invoiceId;

		if (isCreate) {
			// Crear nueva factura con todos sus sub-recursos
			const response = await invoicesApi.create(companyId, payload as CreateInvoiceData);
			if (response.error) {
				const errorMsg = typeof response.error === 'string' ? response.error : m.invoice_edit_form_save_error();
				const error: any = new Error(errorMsg);
				error.validationErrors = response.validationErrors;
				throw error;
			}
			if (!response.data?.id) throw new Error('No se recibió el ID de la factura creada');
			newInvoiceId = response.data.id;

			// Redirigir a la página de edición
			await goto(`/dashboard/invoices/edit/${newInvoiceId}`);
		} else {
			// Actualizar factura existente con todos sus sub-recursos
			const updatePayload = { ...payload, id: invoiceId } as UpdateInvoiceData;
			const response = await invoicesApi.update(invoiceId!, companyId, updatePayload);
			if (response.error) {
				const error: any = new Error(response.error);
				error.validationErrors = response.validationErrors;
				throw error;
			}
		}

		return { success: true, newInvoiceId: newInvoiceId ?? undefined };
	} catch (e) {
		const error = e instanceof Error ? e.message : m.invoice_edit_form_validation_save_error();
		const validationErrors = (e as any)?.validationErrors;
		const apiField = validationErrors?.[0]?.field;
		const firstInvalidField = apiField ? normalizeInvoiceFieldPath(apiField) : undefined;
		return { success: false, error, validationErrors, firstInvalidField };
	}
}

function buildInvoicePayload(formData: FormDataSet): CreateInvoiceData | UpdateInvoiceData {
	const { InvoiceTopFieldsFormData, generalFormData, observationFormData, itemsFormData, othersFormData, continuationFormData } = formData;

	const payload: any = {
		// Datos generales desde InvoiceTopFieldsFormData
		system: 'fixed_asset',
		operation_type: InvoiceTopFieldsFormData?.operation_type || undefined,
		invoice_type: InvoiceTopFieldsFormData?.invoice_type || undefined,
		document_type: generalFormData?.document_type || undefined,
		invoice_number: InvoiceTopFieldsFormData?.invoice_number || undefined,
		purchase_order: InvoiceTopFieldsFormData?.purchase_order || continuationFormData?.purchase_order || undefined,
		invoice_date: InvoiceTopFieldsFormData?.invoice_date || undefined,
		emission_date: InvoiceTopFieldsFormData?.emission_date || undefined,
		proforma_number: observationFormData?.proforma_number || undefined,
		// Observation fields from observationFormData
		observation_es: observationFormData ? observationFormData.observation_es : undefined,
		observation_en: observationFormData ? observationFormData.observation_en : undefined,
		alternate_invoice: InvoiceTopFieldsFormData?.alternate_invoice || (observationFormData ? observationFormData.alternate_invoice : undefined),
		// Fields from othersFormData and continuationFormData that go to invoice header
		related_doc_id: othersFormData?.related_doc_id || undefined,
		vu_observations: othersFormData?.observations_vu || undefined,
		comments_status: othersFormData?.comments_status || undefined,
		option_iv18: othersFormData?.option_iv18 || undefined,

		payment_terms: continuationFormData?.payment_terms || undefined,
		handling_fees: continuationFormData?.handling_fees || undefined,
		cfdi_uuid: continuationFormData?.cfdi_uuid || undefined,
		path_pdf: continuationFormData?.path_pdf || undefined,
		path_xml: continuationFormData?.path_xml || undefined,
	};

	// Solo agregar sub-recursos si tienen valores reales

	// Compliance MX - Siempre incluir si hay headers o valores
	const hasComplianceValue = InvoiceTopFieldsFormData?.pedimento_id || InvoiceTopFieldsFormData?.remesa || generalFormData?.aduana ||
		generalFormData?.provider_id || generalFormData?.sold_to_id ||
		generalFormData?.shipped_to_id || generalFormData?.customs_broker_id ||
		generalFormData?.provider_header || generalFormData?.sold_to_header || generalFormData?.shipped_to_header ||
		observationFormData?.movement_type || observationFormData?.enclosure ||
		othersFormData?.is_mixed || othersFormData?.contingency_mode ||
		othersFormData?.cove || othersFormData?.operation_num ||
		othersFormData?.adendas || othersFormData?.certified_number ||
		othersFormData?.bill_number || othersFormData?.guide_number ||
		othersFormData?.shipment_number || othersFormData?.delivered_status ||
		othersFormData?.received_by || othersFormData?.delivery_date ||
		othersFormData?.code_signature || othersFormData?.electronic_signature ||
		othersFormData?.mandatory_person ||
		continuationFormData?.puerto_entrada || continuationFormData?.reason_export ||
		continuationFormData?.is_mixed !== undefined ||
		observationFormData?.is_mixed !== undefined || observationFormData?.sub_division !== undefined || observationFormData?.office_document !== undefined ||
		generalFormData?.manifest_number !== undefined ||
		generalFormData?.shipped_by_id !== undefined || generalFormData?.shipped_by_header !== undefined;

	if (hasComplianceValue) {
		payload.compliance_mx = buildComplianceMxData(InvoiceTopFieldsFormData?.invoice_type, InvoiceTopFieldsFormData, generalFormData, othersFormData, observationFormData, continuationFormData);
	}

	// Financials
	const hasFinancialsValue = generalFormData?.currency || generalFormData?.currency_type ||
		generalFormData?.iva_factor ||
		observationFormData?.freight || observationFormData?.insurance ||
		observationFormData?.insurance_value || observationFormData?.packaging ||
		observationFormData?.other_increments || observationFormData?.total_increments_mn ||
		observationFormData?.total_increments_me || othersFormData?.print_stamp;

	if (hasFinancialsValue) {
		payload.financials = buildFinancialsData(generalFormData, observationFormData, othersFormData, InvoiceTopFieldsFormData);
	}

	// Logistics
	payload.logistics = buildLogisticsData(generalFormData, observationFormData, othersFormData, continuationFormData);

	// Eliminar campos undefined para no enviarlos
	Object.keys(payload).forEach(key => {
		if (payload[key as keyof typeof payload] === undefined) {
			delete payload[key as keyof typeof payload];
		}
	});

	return payload;
}

function buildComplianceMxData(invoiceType: string, InvoiceTopFieldsFormData: any, generalFormData: any, othersFormData: any, observationFormData: any, continuationFormData: any) {
	return {
		// Pedimento fields - desde InvoiceTopFieldsFormData
		pedimento_id: InvoiceTopFieldsFormData?.pedimento_id ? Number(InvoiceTopFieldsFormData.pedimento_id) : null,
		remesa: InvoiceTopFieldsFormData?.remesa ? Number(InvoiceTopFieldsFormData.remesa) : null,
		is_pedimento_pending: Boolean(InvoiceTopFieldsFormData?.is_pedimento_pending || false),
		// Fields from generalFormData
		aduana: generalFormData?.aduana || null,
		manifest_number: generalFormData?.manifest_number || null,
		port_of_entry: continuationFormData?.puerto_entrada || null,
		provider_header: generalFormData?.provider_header || null,
		provider_id: generalFormData?.provider_id || null,
		sold_to_header: generalFormData?.sold_to_header || null,
		sold_to_id: generalFormData?.sold_to_id || null,
		shipped_to_header: generalFormData?.shipped_to_header || null,
		shipped_to_id: generalFormData?.shipped_to_id || null,
		shipped_by_header: generalFormData?.shipped_by_header || null,
		shipped_by_id: generalFormData?.shipped_by_id || null,
		customs_broker_id: generalFormData?.customs_broker_id ? Number(generalFormData.customs_broker_id) : null,
		customs_broker_us_id: generalFormData?.customs_broker_us_id ? Number(generalFormData.customs_broker_us_id) : null,
		// Fields from observationFormData
		movement_type: observationFormData?.movement_type || null,
		enclosure: observationFormData?.enclosure || null,
		// Fields from othersFormData or continuationFormData (priority based on invoice type)
		is_mixed: invoiceType === 'MEX'
			? (observationFormData?.is_mixed || false)
			: (invoiceType === 'CR' || invoiceType === 'REP' || InvoiceTopFieldsFormData?.operation_type === 'exp'
				? (continuationFormData?.is_mixed === 'si')
				: (othersFormData?.is_mixed === 'si')),
		is_regime_change: invoiceType === 'CR' ? true : (othersFormData?.contingency_mode !== undefined ? othersFormData.contingency_mode : false), // Note: reuse check logic if exists elsewhere, but here we explicitly set it for CR
		reason_export: continuationFormData?.reason_export || null,
		acts_as: othersFormData?.mandatory_person || null,
		contingency_mode: othersFormData?.contingency_mode || false,
		edocument: othersFormData?.cove || null,
		origin_destination_cove: undefined, // Avoid sending invalid enum values, needs proper dropdown
		vucem_operation_num: othersFormData?.operation_num || null,
		addendum_vu: othersFormData?.adendas || null,
		certificate_number: othersFormData?.certified_number || null,
		signature_key: othersFormData?.code_signature || generalFormData?.code_signature || null,
		electronic_signature: othersFormData?.electronic_signature || generalFormData?.electronic_signature || null,
		subdivision: observationFormData?.sub_division || null,
		office_document: observationFormData?.office_document || null,
		rule_3121_parties_ii: othersFormData?.rule_3121_parties_ii || false,
	};
}

function buildFinancialsData(generalFormData: any, observationFormData: any, othersFormData: any, InvoiceTopFieldsFormData?: any) {
	return {
		// Currency from generalFormData
		currency_type: generalFormData?.currency_type || (generalFormData?.currency === 'foreign' ? 'USD' : null),
		currency: generalFormData?.currency || null,
		exchange_rate: generalFormData?.exchange_rate ? Number(generalFormData.exchange_rate) : null,
		iva_factor: (InvoiceTopFieldsFormData?.iva_factor || generalFormData?.iva_factor) ? Number(InvoiceTopFieldsFormData?.iva_factor || generalFormData.iva_factor) : null,
		// Costs & increments from observationFormData
		freight: observationFormData?.freight || null,
		insurance: observationFormData?.insurance || null,
		insurance_value: observationFormData?.insurance_value || null,
		packaging: observationFormData?.packaging || null,
		other_increments: observationFormData?.other_increments || null,
		other_deductibles: observationFormData?.other_deductibles || null,
		total_increments_mn: observationFormData?.total_increments_mn || null,
		total_increments_me: observationFormData?.total_increments_me || null,
		// Seal value from othersFormData
		seal_value_2500: othersFormData?.print_stamp || false,
	};
}

function buildLogisticsData(generalFormData: any, observationFormData: any, othersFormData: any, continuationFormData: any) {
	// Retornar logistics como objeto único con datos de continuación
	return {
		carrier_id: generalFormData?.carrier_id || null,
		transport_id: generalFormData?.transport_id || null,
		transport_type: generalFormData?.transport_type || 'none',
		driver_name: generalFormData?.driver_name || null,
		trailer_num: generalFormData?.trailer_num || null,
		vehicle_num: continuationFormData?.numero_tipo_transporte || null,
		incoterm: observationFormData?.incoterm || null,
		// Número de transporte (anexo) desde continuación; no mezclar con remolque/placa
		transport_num: continuationFormData?.numero_tipo_transporte || null,
		// Identificadores y Complementos
		identifier_1: observationFormData?.identifier_1 || null,
		complement_1: observationFormData?.complement_1 || null,
		identifier_2: observationFormData?.identifier_2 || null,
		complement_2: observationFormData?.complement_2 || null,
		acts_as_cd: observationFormData?.acts_as_cd || continuationFormData?.funge_como_cd || false,
		is_subdivision: (observationFormData?.sub_division === 'si') || continuationFormData?.sub_division || false,
		is_rail: continuationFormData?.es_ferrocarril === 'si' ? true : false,
		bill_number: othersFormData?.bill_number || continuationFormData?.numero_bl || null,
		guide_number: othersFormData?.guide_number || (continuationFormData?.cantidad_guias_embarque ? String(continuationFormData.cantidad_guias_embarque) : null),
		shipment_number: othersFormData?.shipment_number || null,
		delivered_status: othersFormData?.delivered_status || false,
		received_by: othersFormData?.received_by || null,
		delivery_date: othersFormData?.delivery_date || null,
		destination_location: continuationFormData?.destino_origen || null,
		origin_location: continuationFormData?.puerto_entrada || null,
		// Checkboxes de continuación
		equipment_reviewed: continuationFormData?.fue_revisado_equipo || false,
		pedimento_arrived: continuationFormData?.llego_pedimento || false,
		// Semáforos de continuación
		green_light_mx: continuationFormData?.semaforo_verde_aduana_mexicana || false,
		green_light_us: continuationFormData?.semaforo_verde_aduana_americana || false,
		red_light_mx: continuationFormData?.semaforo_rojo_aduana_mexicana || false,
		red_light_us: continuationFormData?.semaforo_rojo_aduana_americana || false,
		// Fechas Logísticas de OthersTabForm (se pasan en othersFormData)
		entry_exit_date: othersFormData?.entry_exit_date || null,
		payment_date: othersFormData?.payment_date || null,

		vehicle_data: continuationFormData?.vehicle_data || null,
	};
}
