/**
 * tencentcloud-webar SDK Type Declarations
 * @module tencentcloud-webar
 * @version 2.x
 */

// ======================== Enums ========================

/** Input type enum */
export enum EntryType {
  CAMERA = 0,
  VIDEO = 1,
  CANVAS = 2,
  IMAGE = 3,
  MEDIA_STREAM = 4,
}

/** Input type constants (equivalent to EntryType) */
export const ENTRY_TYPES: typeof EntryType;

/** Output type enum */
export enum OUTPUT_TYPES {
  CAMERA = 0,
  VIDEO = 1,
  CANVAS = 2,
  IMAGE = 3,
  MEDIA_STREAM = 4,
}

/** Built-in blend modes */
export enum BLEND_MODES {
  NORMAL = 0,
  DARKEN = 1,
  MULTIPLY = 2,
  COLOR_BURN = 3,
  LINEAR_BURN = 4,
  LIGHTEN = 5,
  SCREEN = 6,
  COLOR_DODGE = 7,
  LINEAR_DODGE = 8,
  OVERLAY = 9,
  SOFT_LIGHT = 10,
  HARD_LIGHT = 11,
  VIVID_LIGHT = 12,
  LINEAR_LIGHT = 13,
  PIN_LIGHT = 14,
  HARD_MIX = 15,
  DIFFERENCE = 16,
  EXCLUSION = 17,
  SUBSTRACT = 18,
}

// ======================== Type Definitions ========================

/** Worker mode */
export type WorkerMode = "auto" | "enable" | "disable";

/** Segmentation accuracy level */
export type SegmentationLevel = "auto" | 0 | 1 | 2;

/** Background type */
export type BackgroundType = "blur" | "image" | "transparent" | "green" | "video";

/** Foreground type */
export type ForegroundType = "image" | "video";

/** 3D attach point value */
export type AttachPointValue =
  | "normal"
  | "renzhong"
  | "nosetip"
  | "forehead"
  | "nosebridge"
  | "leftear"
  | "rightear";

// ======================== Config Interfaces ========================

/** Authentication signature data */
export interface AuthData {
  signature: string;
  timestamp: string | number;
}

/** Authentication config */
export interface AuthConfig {
  /** License Key */
  licenseKey: string;
  /** Application ID */
  appId: string;
  /** Signature function that returns auth data */
  authFunc: () => Promise<AuthData>;
}

/** Image input config */
export interface ImageConfig {
  width: number;
  height: number;
  src: HTMLImageElement | string;
}

/** Camera config */
export interface CameraConfig {
  width: number;
  height: number;
  mirror: boolean;
  frameRate: number;
}

/** Loading indicator config */
export interface LoadingConfig {
  enable: boolean;
  size?: number;
  lineWidth?: number;
  strokeColor?: number;
}

/** Beautify parameters */
export interface BeautifyOptions {
  /** Skin whitening, 0-1 */
  whiten?: number;
  /** Skin smoothing, 0-1 */
  dermabrasion?: number;
  /** Dark circle removal */
  darkCircle?: number;
  /** Nasolabial folds removal */
  nasolabialFolds?: number;
  /** Face slimming, 0-1 */
  lift?: number;
  /** Face shaving, 0-1 */
  shave?: number;
  /** Cheekbone adjustment */
  cheekbone?: number;
  /** Head adjustment */
  head?: number;
  /** Eye brightness */
  eyeBrightness?: number;
  /** Lip adjustment */
  lip?: number;
  /** Forehead adjustment */
  forehead?: number;
  /** Nose adjustment */
  nose?: number;
  /** Eye enlargement, 0-1 */
  eye?: number;
  /** Chin adjustment, 0-1 */
  chin?: number;
  /** USM sharpening */
  usm?: number;
  /** Face liquify parameter */
  distort1?: number;
  distortCenter1?: string;
  distortMajorRadius1?: number;
  distortMinorRadius1?: number;
  distort2?: number;
  distortCenter2?: string;
  distortMajorRadius2?: number;
  distortMinorRadius2?: number;
}

/** Beautify options type alias (equivalent to BeautifyOptions) */
export type BEAUTIFY_OPTIONS = BeautifyOptions;

/** Background config */
export interface BackgroundConfig {
  /** Background type */
  type: BackgroundType;
  /** Image/video path, base64, or remote URL */
  src: string;
  /** Solid color value */
  color: number;
  /** Edge blur */
  edgeBlur?: number;
}

/** Foreground config */
export interface ForegroundConfig {
  type: ForegroundType;
  /** Image/video path, base64, or remote URL */
  src: string;
}

/** Proxy server config */
export interface ProxyServerConfig {
  webarProxy?: string;
  staticProxy?: string;
  reportProxy?: string;
}

/** Module enum type */
export type ModuleEnum =
  | "beautify"
  | "segmentation"
  | "handGesture"
  | "handLandmark"
  | "hair";

/** Module config */
export type ModuleConfig = {
  [key in ModuleEnum]?: boolean;
} & {
  segmentationLevel?: SegmentationLevel;
};

/** setEffect parameter format */
export interface SetEffectParam {
  id: string;
  intensity: number;
  filterIntensity: number;
}

/** AR initialization options */
export interface AROptions {
  width?: number;
  height?: number;
  fps?: number;
  input?: MediaStream | HTMLImageElement | string | ImageConfig;
  inputFrameRate?: number;
  mirror?: boolean;
  output?: HTMLCanvasElement;
  enableLoadingIcon?: boolean;
  loadingIconOptions?: {
    size?: number;
    lineWidth?: number;
    strokeColor?: number;
  };
  beautify?: BeautifyOptions;
  hairColor?: string;
  irisScale?: number;
  worker?: WorkerMode;
  resolution?: number | string;
  avatarSize?: number;
  background?: BackgroundConfig;
  segmentationEdgeBlur?: number;
  enableEdgeOptimization?: boolean;
}

/** Common dynamic config */
export interface CommonOptions {
  mirror?: boolean;
}

/** Effect list query parameters */
export interface EffectListParams {
  PageNumber?: number;
  PageSize?: number;
  Version?: string;
  Name?: string;
  Label?: string | string[];
  Type?: string;
}

/** SDK initialization config */
export interface Config {
  /** Authentication parameters */
  auth: AuthConfig;
  /** Module config */
  module: ModuleConfig;
  /** Proxy server config */
  proxyServer?: ProxyServerConfig;
  /** Input stream or image */
  input?: MediaStream | HTMLImageElement | string | ImageConfig;
  /** Whether to mirror the input */
  mirror?: boolean;
  /** Built-in camera config (used when input is not provided) */
  camera?: CameraConfig;
  /** Beautify parameters */
  beautify?: BeautifyOptions;
  /** Built-in loading indicator config */
  loading?: LoadingConfig;
  /** Output canvas element */
  output?: HTMLCanvasElement;
  /** Render frame rate */
  fps?: number;
  /** Virtual background config */
  background?: BackgroundConfig;
  /** Whether to disable keepalive */
  disableKeepalive?: boolean;
  /** Explicit host domain (for Electron compatibility) */
  domain?: string;
  /** i18n language, e.g. "zh", "en" */
  language?: string;
  /** Whether to detect frame rate */
  detectFps?: boolean;
  /** Log level */
  logLevel?: string;
  /** Whether to initialize data reporting, default true */
  initReport?: boolean;
  /** Report region, e.g. "default", "zh", "sg", "us" */
  reportRegion?: string;
  /** Worker mode */
  worker?: WorkerMode;
  /** Resolution */
  resolution?: number | string;
  /** Avatar size */
  avatarSize?: number;
}

// ======================== Event Types ========================

/** SDK event names */
export type ArSdkEventName =
  | "created"
  | "ready"
  | "error"
  | "warning"
  | "cameraReady"
  | "outputReady"
  | "inputStreamChange"
  | "result"
  | "detectStatusChange"
  | "handGesture"
  | "handSwipeRight"
  | "handSwipeLeft"
  | "renderTickerCall"
  | "detectTickerCall";

/** Error event data */
export interface ArSdkError {
  code: number;
  message: string;
  error?: any;
}

/** Detect status change event data */
export interface DetectStatusChangeData {
  [key: string]: any;
}

// ======================== LocalPlayer ========================

/** Local player */
export interface LocalPlayer {
  /** Whether the player is alive */
  alive: boolean;
  /** Set mirror mode */
  setMirror(mirror: boolean): void;
  /** Set muted state */
  setMuted(muted: boolean): void;
  /** Update media stream */
  updateStream(stream: MediaStream): void;
  /** Destroy the player */
  destroy(): void;
}

// ======================== ArSdk Main Class ========================

/**
 * AR SDK Main Class
 *
 * @example
 * ```typescript
 * import { ArSdk, Config } from 'tencentcloud-webar';
 *
 * const config: Config = {
 *   auth: {
 *     licenseKey: 'your-license-key',
 *     appId: 'your-app-id',
 *     authFunc: async () => {
 *       // Request signature from backend
 *       const res = await fetch('/api/get-signature');
 *       return res.json(); // { signature, timestamp }
 *     },
 *   },
 *   module: {
 *     beautify: true,
 *     segmentation: false,
 *   },
 *   input: mediaStream,
 * };
 *
 * const sdk = new ArSdk(config);
 *
 * sdk.on('ready', () => {
 *   sdk.setBeautify({ whiten: 0.5, dermabrasion: 0.5 });
 * });
 *
 * sdk.on('error', (err) => {
 *   console.error(err.code, err.message);
 * });
 * ```
 */
export class ArSdk {
  /** SDK version */
  static readonly sdkVersion: string;

  /** Check if Avatar feature is supported (requires WebGL2) */
  static isAvatarSupported(): boolean;

  /** Camera instance (available after cameraReady event) */
  camera: any;

  /** Whether in lazy initialization mode */
  lazyInit: boolean;

  constructor(config: Config);

  // ==================== Event System ====================

  /**
   * Listen for an event
   * @param name - Event name
   * @param callback - Callback function
   * @returns Listener ID
   */
  on(name: ArSdkEventName | string, callback: (data?: any) => void): number;

  /**
   * Remove an event listener
   * @param name - Event name
   * @param callback - Original callback function reference
   * @param id - Listener ID (optional)
   */
  off(name: ArSdkEventName | string, callback: (data?: any) => void, id?: number): void;

  /**
   * Listen for an event once
   * @param name - Event name
   * @param callback - Callback function
   */
  once(name: ArSdkEventName | string, callback: (data?: any) => void): void;

  /**
   * Check if an event has listeners
   * @param name - Event name
   */
  hasEvent(name: string): boolean;

  // ==================== Input / Output ====================

  /** Set input source */
  set input(src: HTMLImageElement | HTMLVideoElement | MediaStream | string | ImageConfig);

  /** Get current input source */
  get input(): HTMLImageElement | HTMLVideoElement | MediaStream | string | ImageConfig;

  /**
   * Initialize core in lazy mode
   * @param options - Initialization options
   */
  initCore(options?: {
    input?: MediaStream | HTMLImageElement | string | ImageConfig;
    mirror?: boolean;
    camera?: CameraConfig;
    worker?: WorkerMode;
    resolution?: number | string;
  }): Promise<void>;

  /**
   * Get output stream
   * @param fps - Output stream frame rate
   * @param type - Output type; defaults to base64 for image, MediaStream for video
   * @returns MediaStream or base64 string
   */
  getOutput(fps?: number, type?: OUTPUT_TYPES): Promise<MediaStream | string>;

  /**
   * Update input stream (e.g. for switching camera)
   * @param src - New input stream
   * @param stopOldTracks - Whether to stop old media tracks, default true
   * @param updateOutputDestination - Whether to update output destination, default false
   */
  updateInputStream(
    src: MediaStream,
    stopOldTracks?: boolean,
    updateOutputDestination?: boolean
  ): Promise<void>;

  /**
   * Update input image
   * @param options - AR options
   * @param callback - Completion callback
   */
  updateInputImage(options: AROptions, callback?: (...args: any[]) => any): void;

  /**
   * Switch input (for console use)
   * @param type - Input type
   * @param options - AR options
   * @param callback - Completion callback
   */
  setInput(type: EntryType, options: AROptions, callback?: (...args: any[]) => any): void;

  /**
   * Reset core
   * @param input - New input stream (optional)
   */
  resetCore(input?: MediaStream): Promise<void>;

  // ==================== Effects ====================

  /**
   * Preload effect resources by effect IDs
   * @param ids - Effect ID or array of IDs
   * @param callback - Success callback
   * @param errCallback - Error callback
   */
  preloadEffectByIds(
    ids: string | string[],
    callback?: (...args: any[]) => any,
    errCallback?: (...args: any[]) => any
  ): void;

  /**
   * Set effects (makeup / stickers, etc.)
   * @param ids - Effect ID, config object, or array of them
   * @param callback - Success callback
   * @param errCallback - Error callback
   */
  setEffect(
    ids: string | SetEffectParam | (string | SetEffectParam)[],
    callback?: (...args: any[]) => any,
    errCallback?: (...args: any[]) => any
  ): void;

  // ==================== Beautify / Filter ====================

  /**
   * Set beautify parameters
   * @param options - Beautify options
   * @param callback - Completion callback
   */
  setBeautify(options: BeautifyOptions, callback?: (...args: any[]) => any): void;

  /**
   * Set filter
   * @param id - Filter effect ID; pass undefined or "none" to remove filter
   * @param intensity - Filter intensity, default 1
   * @param callback - Success callback
   * @param errCallback - Error callback
   */
  setFilter(
    id?: string,
    intensity?: number,
    callback?: (...args: any[]) => any,
    errCallback?: (...args: any[]) => any
  ): void;

  /**
   * Set hair color
   * @param color - Color value
   */
  setHairColor(color: string): void;

  // ==================== Background / Foreground ====================

  /**
   * Set virtual background
   * @param config - Background config; pass null to remove background
   * @param callback - Completion callback
   */
  setBackground(config: BackgroundConfig | null, callback?: (...args: any[]) => any): Promise<void>;

  /**
   * Set foreground
   * @param config - Foreground config
   * @param callback - Completion callback
   */
  setForeground(config: ForegroundConfig, callback?: (...args: any[]) => any): Promise<void>;

  /**
   * Set segmentation accuracy level
   * @param level - Accuracy level
   */
  setSegmentationLevel(level: SegmentationLevel): Promise<void>;

  // ==================== Avatar ====================

  /**
   * Set avatar
   * @param configs - Avatar configuration
   * @param callback - Success callback
   * @param errCallback - Error callback
   */
  setAvatar(
    configs?: {
      /** Model URL */
      url?: string;
      /** Effect ID */
      effectId?: string;
      /** Avatar mode */
      mode?: "AR" | "VR";
      [key: string]: any;
    },
    callback?: (...args: any[]) => any,
    errCallback?: (...args: any[]) => any
  ): Promise<void>;

  // ==================== Configuration ====================

  /**
   * Set log level
   * @param level - Log level
   */
  setLogLevel(level: string): void;

  /**
   * Set common config (e.g. mirror)
   * @param data - Common config options
   */
  setCommonConfig(data: CommonOptions): void;

  /**
   * Dynamically update detection module config
   * @param data - Module config
   */
  setDetectModuleConfig(data: ModuleConfig): void;

  // ==================== Control ====================

  /** Resume SDK */
  resume(): Promise<void>;

  /** Stop SDK */
  stop(): void;

  /** Disable detection and effects */
  disable(): void;

  /** Enable detection and effects */
  enable(): void;

  // ==================== Misc ====================

  /**
   * Take a photo (returns ImageData)
   */
  takePhoto(): Promise<ImageData>;

  /**
   * Get effect list
   * @param params - Query parameters
   */
  getEffectList(params?: EffectListParams): Promise<any>;

  /**
   * Get avatar list
   * @param type - Type: AR or VR
   */
  getAvatarList(type: "AR" | "VR"): Promise<any>;

  /**
   * Get specific effect info
   * @param effectId - Effect ID
   */
  getEffect(effectId: string): Promise<{ Url: string; [key: string]: any }>;

  /**
   * Get built-in filter list
   */
  getCommonFilter(): Promise<any>;

  /**
   * Initialize local player
   * @param domId - DOM element ID to mount the player
   * @returns Player instance
   */
  initLocalPlayer(domId: string): Promise<LocalPlayer>;

  /**
   * Destroy SDK and release all resources
   * @param options - Destroy options
   * @param options.stopInputStream - Whether to stop input stream tracks, default true
   */
  destroy(options?: { stopInputStream?: boolean }): void;
}

// ======================== Utility Functions ========================

/**
 * Check if the current environment supports WebGL
 */
export function isWebGLSupported(): boolean;

/**
 * Check if the current environment supports WebGL2
 */
export function isWebGL2Supported(): boolean;

/**
 * Check if the current environment supports Worker mode
 */
export function isWorkerAvailable(): boolean;

/**
 * Get current device GPU level
 * @returns GPU level, e.g. "high", "middle", "low"
 */
export function getGPULevel(): string;
