import { __ } from '@wordpress/i18n';
export interface BookingConfig {
    privacyPolicyUrl?: string;
    locale?: string;
    timeFormat?: string;
    requestLocale?: 'user' | 'site';
    timezone?: string;
    membershipsEnabled?: boolean;
    restUrl: string;
    nonce: string;
    authenticated?: boolean;
    loginUrl?: string;
}
export class BookingError extends Error {
    constructor(message: string, public readonly status: number, public readonly code = '', public readonly data?: {
        participant_share_applies?: boolean;
        blockers?: {
            message: string;
        }[];
        usage_limit_warnings?: import('./usage').Usage[];
        customer_restriction_warnings?: {
            message?: string;
        }[];
    }) { super(message); }
}
export class BookingApi {
    constructor(private config: BookingConfig) { }
    privacyPolicyUrl(): string { return this.config.privacyPolicyUrl ?? ''; }
    private async response(route: string, method = 'GET', payload?: unknown, query: Record<string, string> = {}, signal?: AbortSignal): Promise<Response> {
        const url = new URL(this.config.restUrl);
        const restRoute = url.searchParams.get('rest_route');
        if (restRoute !== null)
            url.searchParams.set('rest_route', restRoute + route);
        else
            url.pathname += route;
        if (this.config.requestLocale !== 'site')
            url.searchParams.set('_locale', 'user');
        Object.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));
        const response = await fetch(url, { method, signal, credentials: 'same-origin', headers: { 'X-WP-Nonce': this.config.nonce, 'Content-Type': 'application/json' }, body: payload === undefined ? undefined : JSON.stringify(payload) });
        if (!response.ok) {
            const data = await response.json().catch(() => null);
            throw new BookingError(data?.message ?? __('The request failed. Please try again.', 'abece-booking'), response.status, data?.code, data?.data);
        }
        return response;
    }
    async request<T>(route: string, method = 'GET', payload?: unknown, query: Record<string, string> = {}, signal?: AbortSignal): Promise<T> { return (await this.response(route, method, payload, query, signal)).json(); }
    async list<T>(route: string, query: Record<string, string> = {}): Promise<{
        items: T[];
        total: number;
    }> { const r = await this.response(route, 'GET', undefined, query); return { items: await r.json(), total: Number(r.headers.get('X-WP-Total') ?? 0) }; }
    async all<T>(route: string, query: Record<string, string> = {}): Promise<{
        items: T[];
    }> { const items: T[] = []; for (let page = 1;; page++) {
        const result = await this.list<T>(route, { ...query, per_page: '100', page: String(page) });
        items.push(...result.items);
        if (result.items.length === 0 || page * 100 >= result.total)
            break;
    } return { items }; }
}
