import { Browser, BrowserContextOptions, Page, Locator, LocatorScreenshotOptions, PageScreenshotOptions } from '@playwright/test';
import { Scalar, Range } from '@letsrunit/utils';
import { MetascraperOptions } from 'metascraper';

declare function browse(browser: Browser, options?: BrowserContextOptions): Promise<Page>;

interface SetOptions {
    force?: boolean;
    noWaitAfter?: boolean;
    timeout?: number;
}
type Value = Scalar | Scalar[] | Range | boolean | null;

declare function setFieldValue(el: Locator, value: Value, options?: SetOptions): Promise<void>;

declare function formatHtml(page: string | Page): Promise<string>;

/**
 * Locates an element using Playwright selectors, with lazy fallbacks.
 */
declare function fuzzyLocator(page: Page, selector: string): Promise<Locator>;

interface Snapshot {
    url: string;
    html: string;
    screenshot: File;
}
interface PageInfo {
    /** Page name (from <title> or meta tags) */
    name?: string;
    /** Short page description (meta description or OG/Twitter) */
    description?: string;
    /** Main image for previews (OpenGraph/Twitter) */
    image?: string;
    /** Site or brand logo if available */
    logo?: string;
    /** Author name if specified */
    author?: string;
    /** Publisher or organization name */
    publisher?: string;
    /** Page language, e.g. "en", "nl-NL" */
    lang?: string;
    /** Favicon URL */
    favicon?: string;
    /** Canonical or resolved page URL */
    url: string;
    /** Screenshot of the page */
    screenshot?: File;
}

declare function extractPageInfo(options: MetascraperOptions & Partial<Snapshot>): Promise<PageInfo>;

declare const createDateEngine: () => {
    query(root: Element | Document, body: string): Element | null;
    queryAll(root: Element | Document, body: string): Element[];
    _parseSelector(body: string): Date | null;
    _matchesDate(el: Element, targetDate: Date, locale: string, body: string): {
        matched: boolean;
        type: "full" | "partial";
    };
};

declare const createFieldEngine: () => {
    _compileMatcher(body: string): (s: string | null | undefined) => boolean;
    query(root: Element | Document, body: string): Element | null;
    queryAll(root: Element | Document, body: string): Element[];
};

type SnapshotOptions = {
    /** Strip utility-framework classes (Tailwind, Bootstrap, UnoCSS, Windi) from the captured HTML. */
    dropUtilityClasses?: boolean;
};
declare function snapshot(page: Page, opts?: SnapshotOptions): Promise<Snapshot>;

declare function screenshotElement(page: Page, selector: string, options?: LocatorScreenshotOptions): Promise<File>;
declare function screenshot(page: Page, options?: PageScreenshotOptions): Promise<File>;

declare function scrollToCenter(locator: Locator): Promise<void>;

type Options = {
    timeoutMs?: number;
    preferReject?: boolean;
    lang?: string;
    pollIntervalMs?: number;
    settleAfterActionMs?: number;
    quietPeriodMs?: number;
    minSweepMs?: number;
    maxActions?: number;
    verbose?: boolean;
};
declare function suppressInterferences(page: Page, opts?: Options): Promise<void>;

declare function formatDateForInput(date: Date, type: string | null): string;
declare function formatDate(d: Date, format: string): string;
declare function getMonthNames(locale?: string): string[];

declare function waitForIdle(page: Page, timeout?: number): Promise<void>;
declare function waitForMeta(page: Page, timeout?: number): Promise<void>;
/** Wait until the DOM hasn't changed for `quiet` (default 500ms). */
declare function waitForDomIdle(page: Page, { quiet, timeout }?: {
    quiet?: number;
    timeout?: number;
}): Promise<void>;
declare function waitForAnimationsToFinish(root: Locator): Promise<void>;
declare function waitForUrlChange(page: Page, prevUrl: string, timeout: number): Promise<boolean>;
declare function waitUntilEnabled(page: Page, target: Locator, timeout: number): Promise<void>;
declare function waitAfterInteraction(page: Page, target: Locator, opts?: {
    prevUrl?: string;
    navTimeout?: number;
    settleTimeout?: number;
    quietMs?: number;
}): Promise<void>;

type ScrubHtmlOptions = {
    /** Remove nodes that look hidden/inert by attributes. Default: true */
    dropHidden?: boolean;
    /** Remove the entire <head>. Default: true */
    dropHead?: boolean;
    /** Remove <svg> glyphs. Default: false */
    dropSvg?: boolean;
    /** Only keep <main> element. Default: false */
    pickMain?: boolean;
    /** Keep a conservative attribute allowlist (0=none, 1=normal, 2=aggressive). Default: 1 */
    stripAttributes?: 0 | 1 | 2;
    /** Normalize whitespace in text nodes (outside pre/code). Default: true */
    normalizeWhitespace?: boolean;
    /** Remove HTML comments. Default: true */
    dropComments?: boolean;
    /** Replace <br> within headings (h1–h6) with a space. Default: true */
    replaceBrInHeadings?: boolean;
    /** Limit lists to max items: -1 mean no limit. Default: -1 */
    limitLists?: number;
    /** Strip utility-framework classes (Tailwind, Bootstrap, UnoCSS, Windi) from class
     *  attributes. Removes the attribute entirely when all classes are stripped. Default: false */
    dropUtilityClasses?: boolean;
};
declare function scrubHtml(page: {
    html: string;
    url: string;
} | Page, opts?: ScrubHtmlOptions): Promise<string>;
/**
 * Scrub HTML conservatively for LLMs without destroying semantics.
 */
declare function realScrubHtml({ html, url }: {
    html: string;
    url: string;
}, opts?: ScrubHtmlOptions): Promise<string>;

declare function unifiedHtmlDiff(old: {
    html: string;
    url: string;
} | Page, current: {
    html: string;
    url: string;
} | Page): Promise<string>;

export { type PageInfo, type ScrubHtmlOptions, type Snapshot, type SnapshotOptions, browse, createDateEngine, createFieldEngine, extractPageInfo, formatDate, formatDateForInput, formatHtml, fuzzyLocator, getMonthNames, realScrubHtml, screenshot, screenshotElement, scrollToCenter, scrubHtml, setFieldValue, snapshot, suppressInterferences, unifiedHtmlDiff, waitAfterInteraction, waitForAnimationsToFinish, waitForDomIdle, waitForIdle, waitForMeta, waitForUrlChange, waitUntilEnabled };
