/**
 * REST API カスタムフック
 *
 * wp.apiFetch を使用したCRUD操作のヘルパー。
 */
import apiFetch from '@wordpress/api-fetch';
import { useState, useCallback } from '@wordpress/element';
import { apiErrorMessage } from '../../common/api-error';

const BASE_PATH = '/conf-manager/v1';

/**
 * API リクエスト共通フック
 */
export function useApiRequest() {
	const [ loading, setLoading ] = useState( false );
	const [ error, setError ] = useState( null );

	const request = useCallback( async ( options ) => {
		setLoading( true );
		setError( null );
		try {
			const result = await apiFetch( options );
			return result;
		} catch ( err ) {
			// ⚠️ parse:false を使う呼び出し（members / events の一覧）では失敗時に
			// Response がそのまま throw され err.message が無い。状態コードまで拾う。
			setError( await apiErrorMessage( err, 'API Error' ) );
			throw err;
		} finally {
			setLoading( false );
		}
	}, [] );

	return { request, loading, error, setError };
}

/**
 * 会員 API フック
 */
export function useMemberApi() {
	const { request, loading, error, setError } = useApiRequest();

	const getMembers = useCallback(
		( params = {} ) => {
			const query = new URLSearchParams( params ).toString();
			return request( {
				path: `${ BASE_PATH }/members${ query ? '?' + query : '' }`,
				parse: false,
			} ).then( async ( response ) => {
				const data = await response.json();
				return {
					items: Array.isArray( data ) ? data : [],
					total: parseInt( response.headers.get( 'X-WP-Total' ) || '0' ),
					totalPages: parseInt( response.headers.get( 'X-WP-TotalPages' ) || '1' ),
				};
			} );
		},
		[ request ]
	);

	const getMember = useCallback(
		( id ) => request( { path: `${ BASE_PATH }/members/${ id }` } ),
		[ request ]
	);

	const createMember = useCallback(
		( data ) =>
			request( {
				path: `${ BASE_PATH }/members`,
				method: 'POST',
				data,
			} ),
		[ request ]
	);

	const updateMember = useCallback(
		( id, data ) =>
			request( {
				path: `${ BASE_PATH }/members/${ id }`,
				method: 'PUT',
				data,
			} ),
		[ request ]
	);

	const deleteMember = useCallback(
		( id ) =>
			request( {
				path: `${ BASE_PATH }/members/${ id }`,
				method: 'DELETE',
			} ),
		[ request ]
	);

	return {
		getMembers,
		getMember,
		createMember,
		updateMember,
		deleteMember,
		loading,
		error,
		setError,
	};
}

/**
 * イベント API フック
 */
export function useEventApi() {
	const { request, loading, error, setError } = useApiRequest();

	const getEvents = useCallback(
		( params = {} ) => {
			const query = new URLSearchParams( params ).toString();
			return request( {
				path: `${ BASE_PATH }/events${ query ? '?' + query : '' }`,
				parse: false,
			} ).then( async ( response ) => {
				const data = await response.json();
				return {
					items: Array.isArray( data ) ? data : [],
					total: parseInt(
						response.headers.get( 'X-WP-Total' ) || '0'
					),
				};
			} );
		},
		[ request ]
	);

	const getEvent = useCallback(
		( id ) => request( { path: `${ BASE_PATH }/events/${ id }` } ),
		[ request ]
	);

	const createEvent = useCallback(
		( data ) =>
			request( {
				path: `${ BASE_PATH }/events`,
				method: 'POST',
				data,
			} ),
		[ request ]
	);

	const updateEvent = useCallback(
		( id, data ) =>
			request( {
				path: `${ BASE_PATH }/events/${ id }`,
				method: 'PUT',
				data,
			} ),
		[ request ]
	);

	// 🔴 既定は false。呼び出し側が明示したときだけ申込を巻き込む。
	const deleteEvent = useCallback(
		( id, cancelRegistrations = false ) =>
			request( {
				path: `${ BASE_PATH }/events/${ id }`,
				method: 'DELETE',
				data: { cancel_registrations: cancelRegistrations },
			} ),
		[ request ]
	);

	// 押す前に「何件が巻き込まれるか」を数える。実際に動かす delete と同じリゾルバを読む。
	const getEventCancelImpact = useCallback(
		( id ) => request( { path: `${ BASE_PATH }/events/${ id }/cancel-impact` } ),
		[ request ]
	);

	return {
		getEvents,
		getEvent,
		createEvent,
		updateEvent,
		deleteEvent,
		getEventCancelImpact,
		loading,
		error,
		setError,
	};
}
