/** Query a track by metadata or by its numeric LRCLIB ID. */
type Query = {
    id?: never;
    track_name: string;
    artist_name: string;
    album_name?: string;
    /** Track duration in milliseconds. */
    duration?: number;
} | {
    id: number;
    track_name?: never;
    artist_name?: never;
    album_name?: never;
    duration?: never;
};
/** A successful lyrics response returned by LRCLIB. */
type FindLyricsResponse = {
    id: number;
    name: string;
    trackName: string;
    artistName: string;
    albumName: string;
    duration: number;
    instrumental: boolean;
    plainLyrics: string | null;
    syncedLyrics: string | null;
};
/** The error payload shape used by LRCLIB. */
type ErrorResponse = {
    code: number;
    name: string;
    message: string;
};
type Search = SearchType & {
    artist_name?: string;
    /** Track duration in milliseconds. */
    duration?: number;
};
type SearchType = {
    track_name?: never;
    query: string;
} | {
    track_name: string;
    query?: never;
};
type PublishLyricsBase = {
    trackName: string;
    artistName: string;
    albumName: string;
    /** Track duration in milliseconds. */
    duration: number;
};
/** A publish payload containing plain lyrics, synced lyrics, or both. */
type PublishLyrics = PublishLyricsBase & ({
    plainLyrics: string;
    syncedLyrics?: string;
} | {
    plainLyrics?: string;
    syncedLyrics: string;
});

/** A parsed lyric line. `startTime` is expressed in seconds. */
type LyricLine = {
    text: string;
    startTime?: number;
};
type ParsedLyrics = {
    /** Synchronized lines, or `null` when the input contains no timestamps. */
    synced: LyricLine[] | null;
    /** Lines that do not contain timestamps. */
    unsynced: LyricLine[];
};

/** A fetch-compatible implementation, useful for testing or custom runtimes. */
type FetchImplementation = typeof globalThis.fetch;
type ClientOptions = {
    /** Publish token used only by {@link Client.publishLyrics}. */
    key?: string;
    /** LRCLIB API base URL. Only HTTP(S) URLs without credentials are accepted. */
    url?: string;
    /** Request timeout in milliseconds. Set to `0` to disable it. */
    timeoutMs?: number;
    /** Optional fetch-compatible implementation. */
    fetch?: FetchImplementation;
};
type ChallengeResponse = {
    prefix: string;
    target: string;
};

type RequestErrorOptions = {
    status?: number;
    statusText?: string;
    url?: string;
    cause?: unknown;
};
/** An HTTP, network, timeout, or response-decoding failure. */
declare class RequestError extends Error {
    readonly status?: number;
    readonly statusText?: string;
    readonly url?: string;
    constructor(message?: string, options?: RequestErrorOptions);
}
/** Raised when an operation requires a publish token. */
declare class KeyError extends Error {
    constructor();
}

/** Raised when LRCLIB cannot find the requested track. */
declare class NotFoundError extends RequestError {
    constructor(message?: string, options?: Omit<RequestErrorOptions, "status">);
}
/** Raised when LRCLIB returns no usable result. */
declare class NoResultError extends Error {
    constructor(message?: string);
}

/** A type-safe client for the LRCLIB API. */
declare class Client {
    private readonly baseUrl;
    private readonly publishToken?;
    private readonly timeoutMs;
    private readonly fetchImplementation;
    constructor(options?: ClientOptions);
    private createUrl;
    private safeUrl;
    private request;
    private httpError;
    private readJson;
    /** Searches LRCLIB by free text or track metadata. */
    searchLyrics(info: Search, options?: RequestInit): Promise<FindLyricsResponse[]>;
    /** Gets a track by LRCLIB ID or exact metadata. */
    findLyrics(info: Query, options?: RequestInit): Promise<FindLyricsResponse>;
    /** Gets plain lyrics parsed into individual lines. */
    getUnsynced(info: Query, options?: RequestInit): Promise<LyricLine[] | null>;
    /** Gets synchronized lyrics parsed into lines with start times in seconds. */
    getSynced(info: Query, options?: RequestInit): Promise<LyricLine[] | null>;
    /** Requests the proof-of-work challenge used by LRCLIB publishing clients. */
    requestChallenge(options?: RequestInit): Promise<ChallengeResponse>;
    /**
     * Publishes lyrics with the token supplied in `ClientOptions.key`.
     * Redirects are rejected so the token cannot be forwarded to another origin.
     */
    publishLyrics(info: PublishLyrics, options?: RequestInit): Promise<string>;
}

/**
 * Converts an LRC timestamp (`mm:ss`, `mm:ss.xx`, or `mm:ss.xxx`) to seconds.
 *
 * @throws {TypeError} When the timestamp is malformed.
 */
declare function parseTime(time: string): number;
/**
 * Parses plain or synchronized LRC text without treating metadata tags as lyrics.
 * Multiple timestamps on the same line are supported.
 */
declare function parseLocalLyrics(lyrics: string): ParsedLyrics;

export { type ChallengeResponse, Client, type ClientOptions, type ErrorResponse, type FetchImplementation, type FindLyricsResponse, KeyError, type LyricLine, NoResultError, NotFoundError, type ParsedLyrics, type PublishLyrics, type Query, RequestError, type RequestErrorOptions, type Search, type SearchType, parseLocalLyrics, parseTime };
