import { WritableSignal } from '@angular/core';
import { ClassValue } from 'clsx';
import * as ExcelJS from 'exceljs';
import { Observable } from 'rxjs';
import { FormGroup, FormArray } from '@angular/forms';

type ZBrowserName = 'Chrome' | 'Edge' | 'Firefox' | 'Safari' | 'Opera' | 'IE' | 'Unknown' | string;
type ZDeviceType = 'mobile' | 'tablet' | 'desktop';
interface ZBrowserInfo {
    name: ZBrowserName;
    version: string;
    agent: string;
    device: ZDeviceType;
    time: string;
}
interface ZNavigatorUABrandVersion {
    brand: string;
    version: string;
}
interface ZNavigatorUAData {
    brands: ZNavigatorUABrandVersion[];
    mobile: boolean;
    platform: string;
}
type ZNumberDivide = 'none' | 'thousand' | 'million' | 'billion';
type ZEmptyCheck = 'strict' | 'includeZero';
declare const Z_DIVIDE_SCALE: Record<ZNumberDivide, number>;
declare const Z_LOCALE_MAP: Record<string, string>;
interface ZFormatNumOptions {
    divide?: ZNumberDivide;
    format?: string;
    percent?: boolean;
    emptyCheck?: ZEmptyCheck;
    locale?: string;
    placeholder?: string;
}
declare const Z_EXCEL_NUMBER_FORMAT_MAP: Record<string, string>;
interface ZFormatNumExcelOptions {
    divide?: ZNumberDivide;
    format?: string;
    percent?: boolean;
    emptyCheck?: ZEmptyCheck;
}
declare global {
    interface Navigator {
        userAgentData?: ZNavigatorUAData;
    }
}
type ZCapitalizeType = 'all' | 'sentence' | 'first';

declare const zMergeClasses: (...inputs: ClassValue[]) => string;
declare const zNormalize: (value: string) => string;
declare const zTransform: (value: boolean | string) => boolean;
declare const zUuid: (prefix?: string) => string;
declare const zNoop: () => undefined;
declare const zFormatNum: (value: unknown, options?: ZFormatNumOptions) => string;
declare const zFormatNumExcel: (cell: ExcelJS.Cell | undefined, value: unknown, options?: ZFormatNumExcelOptions) => number | undefined;
declare const zCapitalCase: (text: string, type?: ZCapitalizeType) => string;
declare const zDecodeUnicode: (str: string) => string;
declare const zRandomColor: () => {
    hex: string;
    rgb: string;
    hsl: string;
};
declare const zConvertColorToArgb: (color: string) => string;
declare const zCleanObject: <T = unknown>(obj: T) => T;
declare const zTreeFlatten: <T extends Record<string, unknown>>(list: T[], keyMap: keyof T, parentKeyMap: keyof T, sortFn?: (a: T, b: T) => number) => (T & {
    level: number;
    parentsKey: string[];
})[];
declare const zTreeBuild: <T extends Record<string, unknown>>(list: T[], keyMap: keyof T, parentKeyMap: keyof T, sortFn?: (a: T, b: T) => number) => (T & {
    level: number;
    parentsKey: string[];
    children: unknown[];
})[];
declare const VIETNAMESE_MAP: Record<string, string>;
declare const zRemoveVietnamese: (str: string) => string;
declare const zMiniSearch: <T>(data: T[], query: string, fields: (keyof T | string)[], idField?: keyof T | string) => T[];
declare const zMiniSearch$: <T>(data: T[], query: string, fields: (keyof T | string)[], options?: {
    idField?: keyof T | string;
    loading?: WritableSignal<boolean>;
    fakeDelay?: number;
}) => Observable<T[]>;
declare const zDetectBrowser: () => ZBrowserInfo;

/** Thông tin truy vấn dùng cho autocomplete/select tự tải dữ liệu. */
interface ZAsyncOptionsQuery {
    /** Từ khóa hiện tại người dùng đang nhập. */
    keyword: string;
    /** Trang cần tải, bắt đầu từ 1. */
    page: number;
    /** Số lượng option mong muốn trên mỗi trang. */
    pageSize: number;
}
/** Kết quả trả về từ hàm tải option bất đồng bộ. */
interface ZAsyncOptionsResult<TOption> {
    /** Danh sách option của trang hiện tại. */
    items: TOption[];
    /** Tổng số option trên server, dùng để component tự tính còn trang tiếp theo hay không. */
    total?: number;
    /** Đặt trực tiếp còn dữ liệu hay không khi API không trả total. */
    hasMore?: boolean;
}
/** Kiểu dữ liệu hàm load có thể trả về: sync, Promise hoặc Observable. */
type ZAsyncOptionsLoadResult<TOption> = ZAsyncOptionsResult<TOption> | Promise<ZAsyncOptionsResult<TOption>> | Observable<ZAsyncOptionsResult<TOption>>;
/** Hàm tải option theo keyword/page/pageSize. */
type ZAsyncOptionsLoadFn<TOption> = (query: ZAsyncOptionsQuery) => ZAsyncOptionsLoadResult<TOption>;
/** Config giúp component tự xử lý search, phân trang, loading và chống trùng option. */
interface ZAsyncOptionsConfig<TOption> {
    /** Hàm gọi API hoặc nguồn dữ liệu bất đồng bộ. */
    load: ZAsyncOptionsLoadFn<TOption>;
    /** Số item mỗi lần tải, mặc định 20. */
    pageSize?: number;
    /** Tự tải trang đầu khi dropdown mở/focus, kể cả keyword rỗng. */
    loadOnFocus?: boolean;
    /** Khóa chống trùng khi append trang mới, ví dụ: option => option.value.code. */
    dedupeBy?: (option: TOption) => unknown;
}

/** Số option mặc định mỗi lần component tự gọi load. */
declare const Z_ASYNC_OPTIONS_DEFAULT_PAGE_SIZE = 20;
/** Chuẩn hóa kết quả sync/Promise/Observable về Observable để component xử lý thống nhất. */
declare function zToAsyncOptionsObservable<TOption>(result: ZAsyncOptionsLoadResult<TOption>): Observable<ZAsyncOptionsResult<TOption>>;
/** Gộp option mới vào danh sách cũ và loại bỏ phần tử trùng theo dedupeBy/default key. */
declare function zMergeAsyncOptions<TOption>(current: TOption[], next: TOption[], dedupeBy?: ZAsyncOptionsConfig<TOption>['dedupeBy']): TOption[];
/** Tính còn dữ liệu để load-more dựa trên hasMore, total hoặc độ dài page vừa trả về. */
declare function zResolveAsyncOptionsHasMore<TOption>(result: ZAsyncOptionsResult<TOption>, pageSize: number, loadedCount: number): boolean;
/** Lấy khóa ổn định cho option, hỗ trợ value là object và vẫn cho phép truyền dedupeBy riêng. */
declare function zGetAsyncOptionKey<TOption>(option: TOption, dedupeBy?: ZAsyncOptionsConfig<TOption>['dedupeBy']): unknown;

interface ZEchartsThemeOptions {
    /** Theme name (default: 'zTheme') */
    themeName?: string;
    /** Font family (default: Lexend, Arial, Helvetica, sans-serif) */
    fontFamily?: string;
}

/**
 * Register custom Z-UI theme for ECharts
 * @param options - Theme configuration options
 */
declare function zRegisterEchartsTheme(options?: ZEchartsThemeOptions): void;

/**
 * Submit form and mark invalid controls as dirty (supports nested FormArray/FormGroup)
 * @param form - FormGroup or FormArray to submit
 * @returns true if form is valid, false otherwise
 */
declare const zValidForm: (form: FormGroup | FormArray) => boolean;
/**
 * Debug invalid form controls by logging to console
 * @param form - FormGroup to debug
 * @param parentKey - Parent key for nested controls
 */
declare const zDebugFormInvalid: (form: FormGroup, parentKey?: string) => void;

type ZEmojiCategoryIcon = `lucide${string}` | `sax${string}`;
interface ZEmojiEntry {
    readonly emoji: string;
    readonly keywords: readonly string[];
}
interface ZEmojiCategory {
    id: string;
    labelKey: string;
    icon: ZEmojiCategoryIcon;
    emojis: readonly (string | ZEmojiEntry)[];
}

declare const Z_EMOJI_SHEET: readonly ZEmojiCategory[];

declare const Z_EMOJI_KEYWORDS: ReadonlyMap<string, readonly string[]>;

/**
 * Unified event types for Z-UI form components
 * Allows components to emit native DOM events with type discrimination
 */
type ZEventType = 'focus' | 'blur' | 'keydown' | 'keyup' | 'keypress' | 'click' | 'dblclick' | 'mousedown' | 'mouseup' | 'mouseenter' | 'mouseleave' | 'mouseover' | 'mouseout' | 'touchstart' | 'touchend' | 'touchmove' | 'input' | 'change' | 'paste' | 'copy' | 'cut' | 'dragenter' | 'dragleave' | 'dragover' | 'drop';
interface ZEventBase<T extends ZEventType, E extends Event> {
    type: T;
    event: E;
}
type ZFocusEventData = ZEventBase<'focus', FocusEvent>;
type ZBlurEventData = ZEventBase<'blur', FocusEvent>;
type ZKeydownEventData = ZEventBase<'keydown', KeyboardEvent>;
type ZKeyupEventData = ZEventBase<'keyup', KeyboardEvent>;
type ZKeypressEventData = ZEventBase<'keypress', KeyboardEvent>;
type ZClickEventData = ZEventBase<'click', MouseEvent>;
type ZDblclickEventData = ZEventBase<'dblclick', MouseEvent>;
type ZMousedownEventData = ZEventBase<'mousedown', MouseEvent>;
type ZMouseupEventData = ZEventBase<'mouseup', MouseEvent>;
type ZMouseenterEventData = ZEventBase<'mouseenter', MouseEvent>;
type ZMouseleaveEventData = ZEventBase<'mouseleave', MouseEvent>;
type ZMouseoverEventData = ZEventBase<'mouseover', MouseEvent>;
type ZMouseoutEventData = ZEventBase<'mouseout', MouseEvent>;
type ZTouchstartEventData = ZEventBase<'touchstart', TouchEvent>;
type ZTouchendEventData = ZEventBase<'touchend', TouchEvent>;
type ZTouchmoveEventData = ZEventBase<'touchmove', TouchEvent>;
type ZInputEventData = ZEventBase<'input', InputEvent>;
type ZChangeEventData = ZEventBase<'change', Event>;
type ZPasteEventData = ZEventBase<'paste', ClipboardEvent>;
type ZCopyEventData = ZEventBase<'copy', ClipboardEvent>;
type ZCutEventData = ZEventBase<'cut', ClipboardEvent>;
type ZDragenterEventData = ZEventBase<'dragenter', DragEvent>;
type ZDragleaveEventData = ZEventBase<'dragleave', DragEvent>;
type ZDragoverEventData = ZEventBase<'dragover', DragEvent>;
type ZDropEventData = ZEventBase<'drop', DragEvent>;
type ZEvent = ZFocusEventData | ZBlurEventData | ZKeydownEventData | ZKeyupEventData | ZKeypressEventData | ZClickEventData | ZDblclickEventData | ZMousedownEventData | ZMouseupEventData | ZMouseenterEventData | ZMouseleaveEventData | ZMouseoverEventData | ZMouseoutEventData | ZTouchstartEventData | ZTouchendEventData | ZTouchmoveEventData | ZInputEventData | ZChangeEventData | ZPasteEventData | ZCopyEventData | ZCutEventData | ZDragenterEventData | ZDragleaveEventData | ZDragoverEventData | ZDropEventData;
declare function zCreateEvent<T extends ZEventType>(type: T, event: Event): ZEvent;

type ZFormSubmitResult = boolean;
interface ZFormDebugOptions {
    showValid?: boolean;
    logLevel?: 'error' | 'warn' | 'log';
}

export { VIETNAMESE_MAP, Z_ASYNC_OPTIONS_DEFAULT_PAGE_SIZE, Z_DIVIDE_SCALE, Z_EMOJI_KEYWORDS, Z_EMOJI_SHEET, Z_EXCEL_NUMBER_FORMAT_MAP, Z_LOCALE_MAP, zCapitalCase, zCleanObject, zConvertColorToArgb, zCreateEvent, zDebugFormInvalid, zDecodeUnicode, zDetectBrowser, zFormatNum, zFormatNumExcel, zGetAsyncOptionKey, zMergeAsyncOptions, zMergeClasses, zMiniSearch, zMiniSearch$, zNoop, zNormalize, zRandomColor, zRegisterEchartsTheme, zRemoveVietnamese, zResolveAsyncOptionsHasMore, zToAsyncOptionsObservable, zTransform, zTreeBuild, zTreeFlatten, zUuid, zValidForm };
export type { ZAsyncOptionsConfig, ZAsyncOptionsLoadFn, ZAsyncOptionsLoadResult, ZAsyncOptionsQuery, ZAsyncOptionsResult, ZBlurEventData, ZBrowserInfo, ZBrowserName, ZCapitalizeType, ZChangeEventData, ZClickEventData, ZCopyEventData, ZCutEventData, ZDblclickEventData, ZDeviceType, ZDragenterEventData, ZDragleaveEventData, ZDragoverEventData, ZDropEventData, ZEchartsThemeOptions, ZEmojiCategory, ZEmojiEntry, ZEmptyCheck, ZEvent, ZEventType, ZFocusEventData, ZFormDebugOptions, ZFormSubmitResult, ZFormatNumExcelOptions, ZFormatNumOptions, ZInputEventData, ZKeydownEventData, ZKeypressEventData, ZKeyupEventData, ZMousedownEventData, ZMouseenterEventData, ZMouseleaveEventData, ZMouseoutEventData, ZMouseoverEventData, ZMouseupEventData, ZNavigatorUABrandVersion, ZNavigatorUAData, ZNumberDivide, ZPasteEventData, ZTouchendEventData, ZTouchmoveEventData, ZTouchstartEventData };
