/**
 * Export page — Query builder wizard with stepper.
 *
 * @package RawTypeOE
 */

import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
import { applyFilters } from '@wordpress/hooks';
import { __ } from '@wordpress/i18n';
import { Button, Dialog, Notice, TextField } from '@rawtype/ui';
import useQueryBuilder from '../hooks/useQueryBuilder';
import { useProfiles } from '../hooks/useProfiles';
import { sanitizeKey } from '../utils/crossEntity';
import WizardStepper from './WizardStepper';
import EntitySelector from './EntitySelector';
import FilterBuilder from './FilterBuilder';
import ColumnSelector from './ColumnSelector';
import DataPreview from './DataPreview';

function buildCalculatedFieldColumns( fields ) {
	if ( ! Array.isArray( fields ) ) {
		return [];
	}

	return fields
		.map( ( field, index ) => {
			const rawKey = sanitizeKey( field?.key || '' );
			if ( ! rawKey ) {
				return null;
			}

			return {
				key: 'calc_' + rawKey,
				label: field.label || field.key || rawKey,
				customLabel: null,
				order: index,
			};
		} )
		.filter( Boolean );
}

function renderSection( section, context ) {
	if ( ! section || 'function' !== typeof section.component ) {
		return null;
	}

	const SectionComponent = section.component;
	const props = 'function' === typeof section.getProps
		? section.getProps( context )
		: context;

	return <SectionComponent key={ section.id || section.label } { ...props } />;
}

export default function ExportPage( { initialConfig, initialProfile } ) {
	const qb = useQueryBuilder();
	const { createProfile, updateProfile } = useProfiles();
	const loadedRef = useRef( false );

	const [ saveDialog, setSaveDialog ] = useState( { open: false, name: '', saving: false, error: null } );
	const [ currentProfile, setCurrentProfile ] = useState( null );
	const [ exportOptions, setExportOptions ] = useState( {} );
	const [ calculatedFields, setCalculatedFields ] = useState( [] );

	useEffect( () => {
		if ( loadedRef.current ) {
			return;
		}

		loadedRef.current = true;

		if ( initialConfig ) {
			qb.loadFromConfig( initialConfig );
		} else {
			qb.reset();
		}

		setCurrentProfile( initialProfile || null );
		setSaveDialog( ( prev ) => ( { ...prev, name: initialProfile?.name || '' } ) );
		setExportOptions(
			initialConfig?.options && 'object' === typeof initialConfig.options
				? initialConfig.options
				: {},
		);
		setCalculatedFields(
			Array.isArray( initialConfig?.calculated_fields )
				? initialConfig.calculated_fields
				: [],
		);
	}, [ initialConfig, initialProfile, qb ] );

	useEffect( () => {
		loadedRef.current = false;
	}, [ initialConfig, initialProfile ] );

	const calculatedFieldColumns = useMemo(
		() => buildCalculatedFieldColumns( calculatedFields ),
		[ calculatedFields ],
	);
	const displayColumns = useMemo(
		() => [ ...qb.selectedColumns, ...calculatedFieldColumns ],
		[ qb.selectedColumns, calculatedFieldColumns ],
	);

	const columnsForExport = useMemo(
		() => [
			...qb.getColumnsForExport(),
			...calculatedFieldColumns.map( ( column ) => ( {
				key: column.key,
				label: column.customLabel || column.label,
			} ) ),
		],
		[ qb.selectedColumns, calculatedFieldColumns ],
	);

	const buildExportConfig = () => {
		const config = {
			entity: qb.entity,
			filters: qb.filters.map( ( filter ) => ( {
				field: filter.field,
				operator: filter.operator,
				value: filter.value,
				type: filter.type,
			} ) ),
			logic: qb.logic,
			columns: columnsForExport,
			format: qb.exportFormat,
			options: exportOptions,
			calculated_fields: calculatedFields,
		};

		if ( 'cross-entity' === qb.entity ) {
			config.cross_entity = qb.crossEntityConfig;
		}

		return config;
	};

	const handleSaveProfile = async () => {
		const name = saveDialog.name.trim();
		if ( ! name ) {
			return;
		}

		setSaveDialog( ( prev ) => ( { ...prev, saving: true, error: null } ) );

		try {
			const config = buildExportConfig();
			const result = currentProfile?.id
				? await updateProfile( currentProfile.id, name, config )
				: await createProfile( name, config );

			setCurrentProfile( result );
			setSaveDialog( { open: false, name: result?.name || name, saving: false, error: null } );
		} catch ( err ) {
			// Keep the dialog open with an inline error so the user can retry.
			setSaveDialog( ( prev ) => ( {
				...prev,
				saving: false,
				error: err?.message || __( 'The profile could not be saved. Please try again.', 'rawtype-order-exporter-woocommerce' ),
			} ) );
		}
	};

	const canAdvance = ( stepIndex ) => {
		if ( 0 === stepIndex ) {
			return !! qb.entity;
		}
		return true;
	};

	const handleStepClick = ( index ) => {
		if ( index <= qb.maxStepReached ) {
			qb.goToStep( index );
		}
	};

	const handleNextStep = () => {
		if ( canAdvance( qb.step ) ) {
			qb.nextStep();
		}
	};

	const handleReset = () => {
		qb.reset();
		setCurrentProfile( null );
		setSaveDialog( { open: false, name: '', saving: false, error: null } );
		setExportOptions( {} );
		setCalculatedFields( [] );
	};

	const handleOpenSaveDialog = () => {
		setSaveDialog( ( prev ) => ( {
			...prev,
			open: true,
			error: null,
			name: prev.name.trim() ? prev.name : ( currentProfile?.name || '' ),
		} ) );
	};

	const sectionContext = {
		profile: currentProfile,
		profileName: saveDialog.name,
		selectedColumns: qb.getColumnsForExport(),
		calculatedFields,
		exportOptions,
		onChangeCalculatedFields: setCalculatedFields,
		onChangeExportOptions: setExportOptions,
		onUpdateProfileSchedule: ( schedule ) => {
			setCurrentProfile( ( previous ) =>
				previous ? { ...previous, schedule } : previous,
			);
		},
		onUpdateProfileEmail: ( emailDelivery ) => {
			setCurrentProfile( ( previous ) =>
				previous ? { ...previous, email_delivery: emailDelivery } : previous,
			);
		},
	};

	const exportConfigSections = applyFilters(
		'rawtype_oe_export_config_sections',
		[],
		sectionContext,
	);
	const profileSections = applyFilters(
		'rawtype_oe_profile_sections',
		[],
		sectionContext,
	);

	const hiddenStyle = { display: 'none' };

	return (
		<div className="roe-export-page">
			<WizardStepper
				currentStep={ qb.step }
				maxStepReached={ qb.maxStepReached }
				onStepClick={ handleStepClick }
				totalSteps={ qb.steps.length }
				entity={ qb.entity }
			/>
			<div className="roe-export-page-content">
				<div style={ qb.step !== 0 ? hiddenStyle : undefined }>
					<EntitySelector
						selectedEntity={ qb.entity }
						onSelect={ qb.selectEntity }
						counts={ qb.counts }
						countsLoading={ qb.countsLoading }
						countsError={ qb.countsError }
						onRetry={ qb.loadCounts }
						onNext={ handleNextStep }
					/>
				</div>

				{ qb.maxStepReached >= 1 && (
					<div style={ qb.step !== 1 ? hiddenStyle : undefined }>
						<FilterBuilder
							entity={ qb.entity }
							crossEntityConfig={ qb.crossEntityConfig }
							crossEntityValid={ qb.crossEntityValid }
							onSetCrossPrimary={ qb.setCrossEntityPrimary }
							onToggleCrossRelated={ qb.toggleCrossEntityRelated }
							filters={ qb.filters }
							logic={ qb.logic }
							onSetLogic={ qb.setLogic }
							onAddFilter={ qb.addFilter }
							onUpdateFilter={ qb.updateFilter }
							onRemoveFilter={ qb.removeFilter }
							previewCount={ qb.previewCount }
							previewLoading={ qb.previewLoading }
							previewError={ qb.previewError }
							onNext={ handleNextStep }
							onPrev={ qb.prevStep }
						/>
					</div>
				) }

				{ qb.maxStepReached >= 2 && (
					<div style={ qb.step !== 2 ? hiddenStyle : undefined }>
						<ColumnSelector
							entity={ qb.entity }
							availableColumns={ qb.availableColumns }
							columnsLoading={ qb.columnsLoading }
							columnsError={ qb.columnsError }
							selectedColumns={ qb.selectedColumns }
							onToggleColumn={ qb.toggleColumn }
							onSelectAll={ qb.selectAllColumns }
							onDeselectAll={ qb.deselectAllColumns }
							onResetDefaults={ qb.resetColumnsToDefaults }
							onRenameColumn={ qb.renameColumn }
							onReorderColumns={ qb.reorderColumns }
							onRemoveColumn={ qb.removeColumn }
							showInternalFields={ qb.showInternalFields }
							onToggleShowInternalFields={ qb.setShowInternalFields }
							onRefreshCustomFields={ qb.refreshCustomFields }
							customFieldsRefreshing={ qb.customFieldsRefreshing }
							columnsRefreshing={ qb.columnsRefreshing }
							onNext={ handleNextStep }
							onPrev={ qb.prevStep }
						/>
					</div>
				) }

				{ qb.maxStepReached >= 3 && (
					<div style={ qb.step !== 3 ? hiddenStyle : undefined }>
						<DataPreview
							entity={ qb.entity }
							filters={ qb.filters }
							logic={ qb.logic }
							selectedColumns={ displayColumns }
							getColumnsForExport={ columnsForExport }
							previewCount={ qb.previewCount }
							exportFormat={ qb.exportFormat }
							onSetExportFormat={ qb.setExportFormat }
							exportOptions={ exportOptions }
							onUpdateExportOptions={ setExportOptions }
							crossEntityConfig={ qb.crossEntityConfig }
							crossEntityValid={ qb.crossEntityValid }
							calculatedFields={ calculatedFields }
							onPrev={ qb.prevStep }
							onReset={ handleReset }
							onSaveProfile={ handleOpenSaveDialog }
							visible={ qb.step === 3 }
						/>
						{ exportConfigSections.map( ( section ) => renderSection( section, sectionContext ) ) }
						{ profileSections.map( ( section ) => renderSection( section, sectionContext ) ) }
					</div>
				) }
			</div>

			{ saveDialog.open && (
				<Dialog.Root
					open={ true }
					onOpenChange={ ( open ) => {
						if ( ! open ) {
							setSaveDialog( ( prev ) => ( { ...prev, open: false } ) );
						}
					} }
				>
					<Dialog.Content>
						<Dialog.Title>
							{ currentProfile?.id
								? __( 'Save profile changes', 'rawtype-order-exporter-woocommerce' )
								: __( 'Save export profile', 'rawtype-order-exporter-woocommerce' ) }
						</Dialog.Title>
						<Dialog.Description>
							{ __( 'Give this profile a descriptive name so you can find it easily.', 'rawtype-order-exporter-woocommerce' ) }
						</Dialog.Description>
						{ saveDialog.error && (
							<Notice type="error">{ saveDialog.error }</Notice>
						) }
						<TextField
							placeholder={ __( 'E.g.: Weekly completed orders', 'rawtype-order-exporter-woocommerce' ) }
							value={ saveDialog.name }
							onChange={ ( e ) => setSaveDialog( ( prev ) => ( { ...prev, name: e.target.value } ) ) }
							autoFocus
						/>
						<div className="roe-dialog-actions">
							<Button
								type="button"
								variant="outline"
								onClick={ () => setSaveDialog( ( prev ) => ( { ...prev, open: false } ) ) }
							>
								{ __( 'Cancel', 'rawtype-order-exporter-woocommerce' ) }
							</Button>
							<Button
								type="button"
								onClick={ handleSaveProfile }
								disabled={ ! saveDialog.name.trim() || saveDialog.saving }
							>
								{ saveDialog.saving
									? __( 'Saving...', 'rawtype-order-exporter-woocommerce' )
									: currentProfile?.id
										? __( 'Save changes', 'rawtype-order-exporter-woocommerce' )
										: __( 'Save', 'rawtype-order-exporter-woocommerce' ) }
							</Button>
						</div>
					</Dialog.Content>
				</Dialog.Root>
			) }
		</div>
	);
}
