import { useCallback, useEffect, useState } from '@wordpress/element';
import { __, _n, sprintf } from '@wordpress/i18n';
import { useSearchParams } from 'react-router-dom';
import { ajaxPost } from '../api/ajax';

const TEXT_DOMAIN = 'stock-sync-with-google-sheet-for-woocommerce';

const COLUMNS = [
	{ key: 'product_id', label: __( 'Product ID', TEXT_DOMAIN ) },
	{ key: 'product_name', label: __( 'Product Name', TEXT_DOMAIN ) },
	{ key: 'current_log', label: __( 'Current Log', TEXT_DOMAIN ) },
	{ key: 'previous_log', label: __( 'Previous Log', TEXT_DOMAIN ) },
	{ key: 'earlier_log', label: __( 'Earlier Log', TEXT_DOMAIN ) },
	{ key: 'date', label: __( 'Updated Date', TEXT_DOMAIN ) },
];

/**
 * One snapshot: "Key: value, " pairs like the removed Ssgsw_Log_List::format_recursive_log(), as text.
 */
const Snapshot = ( { log } ) => {
	if ( ! log ) {
		return null;
	}
	if ( ! log.fields ) {
		return log.text || null;
	}
	return log.fields.map( ( field, index ) => (
		<span key={ index } className="ssgsw-log-field">
			<strong>{ field.key }:</strong> { field.value }
			{ index < log.fields.length - 1 ? ', ' : '' }
		</span>
	) );
};

const Pagination = ( { paged, totalPages, totalItems, onPage } ) => {
	const button = ( target, label, text, disabled ) =>
		disabled ? (
			<span className="tablenav-pages-navspan button disabled" aria-hidden="true">
				{ text }
			</span>
		) : (
			<button type="button" className="button" onClick={ () => onPage( target ) }>
				<span className="screen-reader-text">{ label }</span>
				<span aria-hidden="true">{ text }</span>
			</button>
		);

	return (
		<div className="tablenav-pages">
			<span className="displaying-num">
				{ sprintf(
					/* translators: %s: number of log rows. */
					_n( '%s item', '%s items', totalItems, TEXT_DOMAIN ),
					totalItems.toLocaleString()
				) }
			</span>
			{ totalPages > 1 && (
				<span className="pagination-links">
					{ button( 1, __( 'First page', TEXT_DOMAIN ), '«', paged <= 1 ) }{ ' ' }
					{ button( paged - 1, __( 'Previous page', TEXT_DOMAIN ), '‹', paged <= 1 ) }{ ' ' }
					<span className="paging-input">
						{ sprintf(
							/* translators: 1: current page, 2: total pages. */
							__( '%1$s of %2$s', TEXT_DOMAIN ),
							paged,
							totalPages
						) }
					</span>{ ' ' }
					{ button( paged + 1, __( 'Next page', TEXT_DOMAIN ), '›', paged >= totalPages ) }{ ' ' }
					{ button( totalPages, __( 'Last page', TEXT_DOMAIN ), '»', paged >= totalPages ) }
				</span>
			) }
		</div>
	);
};

const Logs = () => {
	const [ params, setParams ] = useSearchParams();
	const search = params.get( 's' ) || '';
	const order = params.get( 'order' ) === 'desc' ? 'desc' : 'asc';
	const paged = Math.max( 1, parseInt( params.get( 'paged' ) || '1', 10 ) || 1 );

	const [ query, setQuery ] = useState( search );
	const [ state, setState ] = useState( { loading: true, error: '', data: null } );

	const update = useCallback(
		( next ) => {
			const merged = { s: search, order, paged: String( paged ), ...next };
			const clean = {};
			Object.entries( merged ).forEach( ( [ key, value ] ) => {
				if ( value && ! ( key === 'paged' && value === '1' ) && ! ( key === 'order' && value === 'asc' ) ) {
					clean[ key ] = value;
				}
			} );
			setParams( clean );
		},
		[ search, order, paged, setParams ]
	);

	useEffect( () => {
		let cancelled = false;
		setState( ( current ) => ( { ...current, loading: true, error: '' } ) );

		ajaxPost( 'ssgsw_get_logs', { s: search, order, paged } )
			.then( ( response ) => {
				if ( cancelled ) {
					return;
				}
				if ( ! response.success ) {
					setState( { loading: false, error: response.message || __( 'Could not load logs.', TEXT_DOMAIN ), data: null } );
					return;
				}
				setState( { loading: false, error: '', data: response.data } );
			} )
			.catch( () => {
				if ( ! cancelled ) {
					setState( { loading: false, error: __( 'Could not load logs.', TEXT_DOMAIN ), data: null } );
				}
			} );

		return () => {
			cancelled = true;
		};
	}, [ search, order, paged ] );

	useEffect( () => setQuery( search ), [ search ] );

	const data = state.data;
	const items = data ? data.items : [];
	const totalItems = data ? data.total_items : 0;
	const totalPages = data ? data.total_pages : 0;

	const onSubmit = ( event ) => {
		event.preventDefault();
		update( { s: query.trim(), paged: '1' } );
	};

	const sortHeader = (
		<th
			scope="col"
			className={ `manage-column column-product_id column-primary sortable ${ order }` }
			aria-sort={ order === 'asc' ? 'ascending' : 'descending' }
		>
			<button
				type="button"
				className="ssgsw-sort-button"
				onClick={ () => update( { order: order === 'asc' ? 'desc' : 'asc', paged: '1' } ) }
			>
				<span>{ COLUMNS[ 0 ].label }</span>
				<span className="sorting-indicators" aria-hidden="true">
					<span className="sorting-indicator asc" />
					<span className="sorting-indicator desc" />
				</span>
			</button>
		</th>
	);

	const navigation = (
		<div className="tablenav">
			<Pagination
				paged={ paged }
				totalPages={ totalPages }
				totalItems={ totalItems }
				onPage={ ( target ) => update( { paged: String( target ) } ) }
			/>
			<br className="clear" />
		</div>
	);

	let body;
	if ( state.loading && ! data ) {
		body = [ 0, 1, 2 ].map( ( row ) => (
			<tr key={ row } className="ssgsw-log-skeleton" aria-hidden="true">
				{ COLUMNS.map( ( column ) => (
					<td key={ column.key }>
						<span />
					</td>
				) ) }
			</tr>
		) );
	} else if ( state.error ) {
		body = (
			<tr className="no-items">
				<td colSpan={ COLUMNS.length } role="alert">
					{ state.error }
				</td>
			</tr>
		);
	} else if ( ! items.length ) {
		body = (
			<tr className="no-items">
				<td colSpan={ COLUMNS.length }>
					{ search ? __( 'No logs match this product ID.', TEXT_DOMAIN ) : __( 'No logs yet', TEXT_DOMAIN ) }
				</td>
			</tr>
		);
	} else {
		body = items.map( ( item ) => (
			<tr key={ item.id || item.product_id }>
				<td className="column-primary" data-colname={ COLUMNS[ 0 ].label }>
					{ item.product_id }
				</td>
				<td data-colname={ COLUMNS[ 1 ].label }>{ item.product_name }</td>
				<td data-colname={ COLUMNS[ 2 ].label }>
					<Snapshot log={ item.current_log } />
				</td>
				<td data-colname={ COLUMNS[ 3 ].label }>
					<Snapshot log={ item.previous_log } />
				</td>
				<td data-colname={ COLUMNS[ 4 ].label }>
					<Snapshot log={ item.earlier_log } />
				</td>
				<td data-colname={ COLUMNS[ 5 ].label }>{ item.date }</td>
			</tr>
		) );
	}

	return (
		<div className="wrap ssgsw-logs-page">
			<h1>{ __( 'All Logs', TEXT_DOMAIN ) }</h1>

			<form className="ssgsw-logs-search" role="search" onSubmit={ onSubmit }>
				<p className="search-box">
					<label className="screen-reader-text" htmlFor="ssgsw-log-search">
						{ __( 'Search ID', TEXT_DOMAIN ) }
					</label>
					<input
						type="search"
						id="ssgsw-log-search"
						inputMode="numeric"
						value={ query }
						onChange={ ( event ) => setQuery( event.target.value ) }
					/>
					<button type="submit" className="button">
						{ __( 'Search ID', TEXT_DOMAIN ) }
					</button>
				</p>
			</form>

			{ navigation }

			<table className="wp-list-table widefat fixed striped ssgsw-logs-table" aria-busy={ state.loading }>
				<thead>
					<tr>
						{ sortHeader }
						{ COLUMNS.slice( 1 ).map( ( column ) => (
							<th key={ column.key } scope="col" className={ `manage-column column-${ column.key }` }>
								{ column.label }
							</th>
						) ) }
					</tr>
				</thead>
				<tbody>{ body }</tbody>
			</table>

			{ totalPages > 1 && navigation }
		</div>
	);
};

export default Logs;
