import type { Options as HtmlMinifierOptions } from 'html-minifier-terser';
import type { PluginVisualizerOptions } from 'rollup-plugin-visualizer';
import type { PluginOptions } from 'unplugin-dts';
import type {
  ConfigEnv,
  PluginOption,
  UserConfig,
  UserConfigFnPromise,
} from 'vite';
import type { Options as PwaPluginOptions } from 'vite-plugin-pwa';

/**
 * ImportMap 配置接口
 * @description 用于配置模块导入映射，支持自定义导入路径和范围
 * @example
 * ```typescript
 * {
 *   imports: {
 *     'vue': 'https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js'
 *   },
 *   scopes: {
 *     'https://site.com/': {
 *       'vue': 'https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js'
 *     }
 *   }
 * }
 * ```
 */
interface IImportMap {
  /** 模块导入映射 */
  imports?: Record<string, string>;
  /** 作用域特定的导入映射 */
  scopes?: {
    [scope: string]: Record<string, string>;
  };
}

/**
 * 打印插件配置选项
 * @description 用于配置控制台打印信息
 */
interface PrintPluginOptions {
  /**
   * 打印的数据映射
   * @description 键值对形式的数据，将在控制台打印
   * @example
   * ```typescript
   * {
   *   'App Version': '1.0.0',
   *   'Build Time': '2024-01-01'
   * }
   * ```
   */
  infoMap?: Record<string, string | undefined>;
}

/**
 * Nitro Mock 插件配置选项
 * @description 用于配置 Nitro Mock 服务器的行为
 */
interface NitroMockPluginOptions {
  /**
   * Mock 服务器包名
   * @default '@vbenjs/nitro-mock'
   */
  mockServerPackage?: string;

  /**
   * Mock 服务端口
   * @default 3000
   */
  port?: number;

  /**
   * 是否打印 Mock 日志
   * @default false
   */
  verbose?: boolean;
}

/**
 * 归档插件配置选项
 * @description 用于配置构建产物的压缩归档
 */
interface ArchiverPluginOptions {
  /**
   * 输出文件名
   * @default 'dist'
   */
  name?: string;
  /**
   * 输出目录
   * @default '.'
   */
  outputDir?: string;
}

/**
 * HTML 插件配置
 * @description 用于配置基于 transformIndexHtml 的 HTML 压缩行为
 */
type HtmlPluginOptions = HtmlMinifierOptions;

/**
 * ImportMap 插件配置
 * @description 用于配置模块的 CDN 导入
 */
interface ImportmapPluginOptions {
  /**
   * CDN 供应商
   * @default 'jspm.io'
   * @description 支持 esm.sh 和 jspm.io 两种 CDN 供应商
   */
  defaultProvider?: 'esm.sh' | 'jspm.io';
  /**
   * ImportMap 配置数组
   * @description 配置需要从 CDN 导入的包
   * @example
   * ```typescript
   * [
   *   { name: 'vue' },
   *   { name: 'pinia', range: '^2.0.0' }
   * ]
   * ```
   */
  importmap?: Array<{ name: string; range?: string }>;
  /**
   * 手动配置 ImportMap
   * @description 自定义 ImportMap 配置
   */
  inputMap?: IImportMap;
}

/**
 * 条件插件配置
 * @description 用于根据条件动态加载插件
 */
interface ConditionPlugin {
  /**
   * 判断条件
   * @description 当条件为 true 时加载插件
   */
  condition?: boolean;
  /**
   * 插件对象
   * @description 返回插件数组或 Promise
   */
  plugins: () => PluginOption[] | PromiseLike<PluginOption[]>;
}

/**
 * 通用插件配置选项
 * @description 所有插件共用的基础配置
 */
interface CommonPluginOptions {
  /**
   * 是否开启开发工具
   * @default false
   */
  devtools?: boolean;
  /**
   * 环境变量
   * @description 自定义环境变量
   */
  env?: Record<string, any>;
  /**
   * 是否注入元数据
   * @default true
   */
  injectMetadata?: boolean;
  /**
   * 是否为构建模式
   * @default false
   */
  isBuild?: boolean;
  /**
   * 构建模式
   * @default 'development'
   */
  mode?: string;
  /**
   * 是否开启依赖分析
   * @default false
   * @description 使用 rollup-plugin-visualizer 分析依赖
   */
  visualizer?: boolean | PluginVisualizerOptions;
}

/**
 * 应用插件配置选项
 * @description 用于配置应用构建时的插件选项
 */
interface ApplicationPluginOptions extends CommonPluginOptions {
  /**
   * 是否开启压缩归档
   * @default false
   * @description 开启后会在打包目录生成 zip 文件
   */
  archiver?: boolean;
  /**
   * 压缩归档插件配置
   * @description 配置压缩归档的行为
   */
  archiverPluginOptions?: ArchiverPluginOptions;
  /**
   * 是否开启压缩
   * @default false
   * @description 支持 gzip 和 brotli 压缩
   */
  compress?: boolean;
  /**
   * 压缩类型
   * @default ['gzip']
   * @description 可选的压缩类型
   */
  compressTypes?: ('brotli' | 'gzip')[];
  /**
   * 是否开启 dayjs 插件
   * @default true
   */
  dayjs?: boolean;
  /**
   * 是否抽离配置文件
   * @default false
   * @description 在构建时抽离配置文件
   */
  extraAppConfig?: boolean;
  /**
   * 是否开启 HTML 插件
   * @default true
   */
  html?: boolean | HtmlPluginOptions;
  /**
   * 是否开启国际化
   * @default false
   */
  i18n?: boolean;
  /**
   * 是否开启 ImportMap CDN
   * @default false
   */
  importmap?: boolean;
  /**
   * ImportMap 插件配置
   */
  importmapOptions?: ImportmapPluginOptions;
  /**
   * 是否注入应用加载动画
   * @default true
   */
  injectAppLoading?: boolean;
  /**
   * 是否注入全局 SCSS
   * @default true
   */
  injectGlobalScss?: boolean;
  /**
   * 是否注入版权信息
   * @default true
   */
  license?: boolean;
  /**
   * 是否开启 Nitro Mock
   * @default false
   */
  nitroMock?: boolean;
  /**
   * Nitro Mock 插件配置
   */
  nitroMockOptions?: NitroMockPluginOptions;
  /**
   * 是否开启控制台打印
   * @default false
   */
  print?: boolean;
  /**
   * 打印插件配置
   */
  printInfoMap?: PrintPluginOptions['infoMap'];
  /**
   * 是否开启 PWA
   * @default false
   */
  pwa?: boolean;
  /**
   * PWA 插件配置
   */
  pwaOptions?: Partial<PwaPluginOptions>;
  /**
   * 是否开启 VXE Table 懒加载
   * @default false
   */
  vxeTableLazyImport?: boolean;
}

/**
 * 库插件配置选项
 * @description 用于配置库构建时的插件选项
 */
interface LibraryPluginOptions extends CommonPluginOptions {
  /**
   * 是否开启 DTS 输出
   * @default true
   * @description 生成 TypeScript 类型声明文件
   */
  dts?: boolean | PluginOptions;
}

/**
 * 应用配置选项类型
 */
type ApplicationOptions = ApplicationPluginOptions;

/**
 * 库配置选项类型
 */
type LibraryOptions = LibraryPluginOptions;

/**
 * 应用配置定义函数类型
 * @description 用于定义应用构建配置
 */
type DefineApplicationOptions = (config?: ConfigEnv) => Promise<{
  /** 应用插件配置 */
  application?: ApplicationOptions;
  /** Vite 配置 */
  vite?: UserConfig;
}>;

/**
 * 库配置定义函数类型
 * @description 用于定义库构建配置
 */
type DefineLibraryOptions = (config?: ConfigEnv) => Promise<{
  /** 库插件配置 */
  library?: LibraryOptions;
  /** Vite 配置 */
  vite?: UserConfig;
}>;

/**
 * 配置定义类型
 * @description 应用或库的配置定义
 */
type DefineConfig = DefineApplicationOptions | DefineLibraryOptions;

type VbenViteConfig = Promise<UserConfig> | UserConfig | UserConfigFnPromise;

export type {
  ApplicationPluginOptions,
  ArchiverPluginOptions,
  CommonPluginOptions,
  ConditionPlugin,
  DefineApplicationOptions,
  DefineConfig,
  DefineLibraryOptions,
  HtmlPluginOptions,
  IImportMap,
  ImportmapPluginOptions,
  LibraryPluginOptions,
  NitroMockPluginOptions,
  PrintPluginOptions,
  VbenViteConfig,
};
