/**
 * Packaging section: one accordion per order item. Manual dimensions only.
 * Header = item name + dimensions (truncated). Expanded: manual L/W/H/weight; Apply refetches quotes.
 */
import { __ } from '@wordpress/i18n';
import { useState, useCallback, memo } from '@wordpress/element';
import {
	Button,
	Card,
	CardBody,
	Flex,
	FlexItem,
	Notice,
	TextControl,
} from '@wordpress/components';
import { chevronDown, chevronUp } from '@wordpress/icons';
import { Icon } from '@wordpress/components';
import { useWindowSize } from '../../shared/hooks';
import {
	formatDisplayNumber,
	getDimensionBounds,
	getWeightBounds,
	parseWeight,
	getApiErrorMessage,
	truncateText,
} from '../../shared/utils';
import type { Order, OrderItem } from '../../types';
import type { QuotePayload } from '../../types/quote';
import {
	buildQuotePayloadFromItems,
	type ItemDimensions,
} from './utils/orderToQuotePayload';
import { StoreSettingsResponse } from 'types/settings';

const MAX_TITLE_LENGTH = 40;
const DEFAULT_DIM = 10;
const DEFAULT_WEIGHT = 1;


function itemDims(dims: OrderItem['dimensions'] | undefined): ItemDimensions {
	const length = dims?.length != null ? Number(dims.length) : 0;
	const width = dims?.width != null ? Number(dims.width) : 0;
	const height = dims?.height != null ? Number(dims.height) : 0;
	const weight = dims?.weight != null ? parseWeight(dims.weight) : 0;
	return {
		length: length > 0 ? length : DEFAULT_DIM,
		width: width > 0 ? width : DEFAULT_DIM,
		height: height > 0 ? height : DEFAULT_DIM,
		weight: weight > 0 ? weight : DEFAULT_WEIGHT,
	};
}

export interface PackagingSectionProps {
	order: Order;
	store: StoreSettingsResponse | null;
	onFetchQuotes: (payload: QuotePayload) => Promise<void>;
}

interface PackageItemProps {
	item: OrderItem;
	index: number;
	isExpanded: boolean;
	dimensions: ItemDimensions;
	manualOverride: ItemDimensions | null;
	dUnit: string;
	wUnit: string;
	isApplying: boolean;
	isWide: boolean;
	onToggle: () => void;
	onOverrideChange: (dims: ItemDimensions | null) => void;
	onApply: () => void;
	isLastItem: boolean;
}

const PackageItem = memo<PackageItemProps>(function PackageItem({
	item,
	isExpanded,
	dimensions,
	manualOverride,
	dUnit,
	wUnit,
	isApplying,
	isWide,
	onToggle,
	onOverrideChange,
	onApply,
	isLastItem,
}) {
	const title = truncateText(item.name, MAX_TITLE_LENGTH);
	const displayDims = manualOverride ?? dimensions;
	const dimensionsText = `(${formatDisplayNumber(displayDims.length)}×${formatDisplayNumber(displayDims.width)}×${formatDisplayNumber(displayDims.height)})${dUnit}`;
	const dimensionBounds = getDimensionBounds(dUnit || 'cm');
	const weightBounds = getWeightBounds(wUnit || 'kg');

	const setManualDim = useCallback(
		(field: keyof ItemDimensions, value: number) => {
			onOverrideChange({
				length: field === 'length' ? value : displayDims.length,
				width: field === 'width' ? value : displayDims.width,
				height: field === 'height' ? value : displayDims.height,
				weight: field === 'weight' ? value : displayDims.weight,
			});
		},
		[onOverrideChange, displayDims]
	);

	return (
		<div
			style={{
				borderBottom: !isLastItem ? '1px solid #ddd' : undefined,
			}}
		>
			<button
				type="button"
				onClick={onToggle}
				style={{
					width: '100%',
					display: 'flex',
					alignItems: 'center',
					justifyContent: 'space-between',
					padding: '12px 16px',
					background: 'none',
					border: 'none',
					cursor: 'pointer',
					textAlign: 'left',
					fontSize: 14,
				}}
				aria-expanded={isExpanded}
			>
				<span>
					<strong>{title} - </strong> {dimensionsText}
				</span>
				<Icon icon={isExpanded ? chevronUp : chevronDown} size={24} />
			</button>

			{isExpanded && (
				<div style={{ padding: '0 16px 16px' }}>
					<Flex direction="column" gap={4}>
						<p style={{ margin: 0, fontSize: 12, color: '#757575' }}>
							{__('Enter dimensions manually', 'parcel2go-shipping')}
						</p>
						<Flex
							direction={isWide ? 'row' : 'column'}
							gap={3}
							wrap
							style={{ flexWrap: 'wrap' }}
						>
							<FlexItem style={{ minWidth: isWide ? 80 : undefined }}>
								<TextControl
									label={`L (${dUnit})`}
									type="number"
									min={dimensionBounds.min}
									max={dimensionBounds.max}
									step={dimensionBounds.step}
									value={String(displayDims.length)}
									onChange={(v) =>
										setManualDim('length', parseFloat(v || '0') || 0)
									}
								/>
							</FlexItem>
							<FlexItem style={{ minWidth: isWide ? 80 : undefined }}>
								<TextControl
									label={`W (${dUnit})`}
									type="number"
									min={dimensionBounds.min}
									max={dimensionBounds.max}
									step={dimensionBounds.step}
									value={String(displayDims.width)}
									onChange={(v) =>
										setManualDim('width', parseFloat(v || '0') || 0)
									}
								/>
							</FlexItem>
							<FlexItem style={{ minWidth: isWide ? 80 : undefined }}>
								<TextControl
									label={`H (${dUnit})`}
									type="number"
									min={dimensionBounds.min}
									max={dimensionBounds.max}
									step={dimensionBounds.step}
									value={String(displayDims.height)}
									onChange={(v) =>
										setManualDim('height', parseFloat(v || '0') || 0)
									}
								/>
							</FlexItem>
							<FlexItem style={{ minWidth: isWide ? 80 : undefined }}>
								<TextControl
									label={`${__('Weight', 'parcel2go-shipping')} (${wUnit})`}
									type="number"
									min={weightBounds.min}
									step={weightBounds.step}
									value={String(displayDims.weight)}
									onChange={(v) =>
										setManualDim('weight', parseFloat(v || '0') || 0)
									}
								/>
							</FlexItem>
						</Flex>

						<Flex align="center" justify="flex-start" gap={3}>
							<Button
								variant="primary"
								isBusy={isApplying}
								onClick={onApply}
							>
								{isApplying
									? __('Applying...', 'parcel2go-shipping')
									: __('Apply', 'parcel2go-shipping')}
							</Button>
						</Flex>
					</Flex>
				</div>
			)}
		</div>
	);
});

export default function PackagingSection({
	order,
	store,
	onFetchQuotes,
}: PackagingSectionProps) {
	const items = order.items ?? [];
	const dUnit = order.units?.dimension ?? 'cm';
	const wUnit = order.units?.weight ?? 'kg';

	const [expandedIndex, setExpandedIndex] = useState<number | null>(null);
	const [overrides, setOverrides] = useState<Record<number, ItemDimensions>>({});
	const [applyingIndex, setApplyingIndex] = useState<number | null>(null);
	const [successMessage, setSuccessMessage] = useState<string | null>(null);
	const [applyError, setApplyError] = useState<string | null>(null);

	const { width } = useWindowSize();
	const isWide = width >= 600;

	const getItemDimensions = useCallback(
		(index: number, item: OrderItem): ItemDimensions => {
		const itemOverride = overrides[index];
		if (itemOverride) {
			return itemOverride;
		}
			return itemDims(item.dimensions);
		},
		[overrides]
	);

	const handleApply = useCallback(
		async (itemIndex: number) => {
			const payload = buildQuotePayloadFromItems(order, store, getItemDimensions);

			if (!payload) return;

			setApplyingIndex(itemIndex);
			setApplyError(null);
			setSuccessMessage(null);

			try {
				await onFetchQuotes(payload);
				setSuccessMessage(__('Quotes updated successfully.', 'parcel2go-shipping'));
			} catch (err: unknown) {
				setApplyError(
					getApiErrorMessage(
						err,
						__('Failed to update quotes. Please try again.', 'parcel2go-shipping')
					)
				);
			} finally {
				setApplyingIndex(null);
			}
		},
		[order, store, getItemDimensions, onFetchQuotes]
	);

	const setOverride = useCallback((index: number, dims: ItemDimensions | null) => {
		setOverrides((prev) => {
			if (dims == null) {
				const next = { ...prev };
				delete next[index];
				return next;
			}
			return { ...prev, [index]: dims };
		});
	}, []);

	if (!items.length) {
		return (
			<Card size="large" style={{ background: '#f6f7f7' }}>
				<CardBody>
					<p style={{ margin: 0, color: '#646970' }}>
						{__('No items in this order.', 'parcel2go-shipping')}
					</p>
				</CardBody>
			</Card>
		);
	}

	return (
		<Card size="large" style={{ background: '#f6f7f7' }}>
			<CardBody>
				<h3
					style={{
						margin: '0 0 12px',
						fontWeight: 600,
						fontSize: '1rem',
					}}
				>
					{__('Packaging', 'parcel2go-shipping')}
				</h3>

				{successMessage && (
					<Notice
						status="success"
						isDismissible
						onRemove={() => setSuccessMessage(null)}
					>
						{successMessage}
					</Notice>
				)}

				{applyError && (
					<Notice
						status="error"
						isDismissible
						onRemove={() => setApplyError(null)}
					>
						{applyError}
					</Notice>
				)}

				<Flex direction="column" gap={0}>
					{items.map((item, index) => {
						const dimensions = getItemDimensions(index, item);

						return (
							<PackageItem
								key={`${item.product_id}-${item.variation_id}-${index}`}
								item={item}
								index={index}
								isExpanded={expandedIndex === index}
								dimensions={dimensions}
								manualOverride={overrides[index] ?? null}
								dUnit={dUnit}
								wUnit={wUnit}
								isApplying={applyingIndex === index}
								isWide={isWide}
								onToggle={() =>
									setExpandedIndex(expandedIndex === index ? null : index)
								}
								onOverrideChange={(dims) => setOverride(index, dims)}
								onApply={() => handleApply(index)}
								isLastItem={index === items.length - 1}
							/>
						);
					})}
				</Flex>
			</CardBody>
		</Card>
	);
}
