declare interface Where {
  /**
   * 过滤`null`的参数
   */
  notNull(): Where;

  /**
   * 过滤`null`的参数
   * @param flag 是否过滤
   */
  notNull(flag: boolean): Where;

  /**
   * 过滤`blank`的参数
   */
  notBlank(): Where;

  /**
   * 过滤`blank`的参数
   * @param flag 是否过滤
   */
  notBlank(flag: boolean): Where;

  /**
   * 等于`=`,如：`eq('name', '老王') ---> name = '老王'`
   * @param column 数据库中的列名
   * @param value 值
   */
  eq(column: string, value: any): Where;

  /**
   * 等于`=`,如：`eq('name', '老王') ---> name = '老王'`
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  eq(condition: boolean, column: string, value: any): Where;

  /**
   * 不等于`<>`,如：`ne('name', '老王') ---> name <> '老王'`
   * @param column 数据库中的列名
   * @param value 值
   */
  ne(column: string, value: any): Where;

  /**
   * 不等于`<>`,如：`ne('name', '老王') ---> name <> '老王'`
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  ne(condition: boolean, column: string, value: any): Where;

  /**
   * 小于`<`,如：`lt('age', 18) ---> age < 18
   * @param column 数据库中的列名
   * @param value 值
   */
  lt(column: string, value: any): Where;

  /**
   * 小于`<`,如：`lt('age', 18) ---> age < 18
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  lt(condition: boolean, column: string, value: any): Where;

  /**
   * 小于等于`<=`,如：`lte('age', 18) ---> age <= 18
   * @param column 数据库中的列名
   * @param value 值
   */
  lte(column: string, value: any): Where;

  /**
   * 小于等于`<=`,如：`lte('age', 18) ---> age <= 18
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  lte(condition: boolean, column: string, value: any): Where;

  /**
   * 大于`>`,如：`gt('age', 18) ---> age > 18
   * @param column 数据库中的列名
   * @param value 值
   */
  gt(column: string, value: any): Where;

  /**
   * 大于`>`,如：`gt('age', 18) ---> age > 18
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  gt(condition: boolean, column: string, value?: any): Where;

  /**
   * 大于等于`>=`,如：`gte('age', 18) ---> age >= 18
   * @param column 数据库中的列名
   * @param value 值
   */
  gte(column: string, value: any): Where;

  /**
   * 大于等于`>=`,如：`gte('age', 18) ---> age >= 18
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  gte(condition: boolean, column: string, value: any): Where;

  /**
   * `in`,如：`in('age', [1,2,3]) ---> age in (1,2,3)
   * @param column 数据库中的列名
   * @param value 值
   */
  in(column: string, value: any): Where;

  /**
   * `in`,如：`in('age', [1,2,3]) ---> age in (1,2,3)
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  in(condition: boolean, column: string, value: any): Where;

  /**
   * `not in`,如：`notIn('age', [1,2,3]) ---> age not in (1,2,3)
   * @param column 数据库中的列名
   * @param value 值
   */
  notIn(column: string, value: any): Where;

  /**
   * `not in`,如：`notIn('age', [1,2,3]) ---> age not in (1,2,3)
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  notIn(condition: boolean, column: string, value: any): Where;

  /**
   * `like`,如：`like('name', '%王%') ---> name like '%王%'
   * @param column 数据库中的列名
   * @param value 值
   */
  like(column: string, value: any): Where;

  /**
   * `like`,如：`like('name', '%王%') ---> name like '%王%'
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  like(condition: boolean, column: string, value: any): Where;

  /**
   * not like`,如：`notLike('name', '%王%') ---> name not like '%王%'
   * @param column 数据库中的列名
   * @param value 值
   */
  notLike(column: string, value: any): Where;

  /**
   * not like`,如：`notLike('name', '%王%') ---> name not like '%王%'
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   * @param value 值
   */
  notLike(condition: boolean, column: string, value: any): Where;

  /**
   * `is null`,如：`isNull('name') ---> name is null
   * @param column 数据库中的列名
   */
  isNull(column: string): Where;

  /**
   * `is null`,如：`isNull('name') ---> name is null
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   */
  isNull(condition: boolean, column: string): Where;

  /**
   * `is not null`,如：`isNotNull('name') ---> name is not null
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   */
  isNotNull(column: string): Where;

  /**
   * `is not null`,如：`isNotNull('name') ---> name is not null
   * @param condition 判断表达式，当为true时拼接条件
   * @param column 数据库中的列名
   */
  isNotNull(condition: boolean, column: string): Where;

  /**
   * 拼接`or`
   */
  or(): Where;

  /**
   * 拼接`and`
   */
  and(): Where;

  /**
   * `and`嵌套，如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')
   * @param condition 判断表达式，当为true时拼接条件
   * @param _function 回调函数
   */
  and(_function: (where: Where) => Where): Where;

  /**
   * `and`嵌套，如and(it => it.eq('name','李白').ne('status','正常') --> and (name = '李白' and status <> '正常')
   * @param condition 判断表达式，当为true时拼接条件
   * @param _function 回调函数
   */
  and(condition: boolean, _function: (where: Where) => Where): Where;

  /**
   * 拼接`order by xxx asc/desc`
   * @param column 要排序的列
   * @param sort `asc`或`desc` default asc
   */
  orderBy(column: string, sort?: 'asc' | 'desc'): Where;

  /**
   * 拼接拼接`order by xxx desc`
   * @param column 要排序的列
   */
  orderByDesc(column: string): Where;

  /**
   * 拼接`group by`
   * @param columns 要分组的列
   */
  groupBy(...columns: string[]): Where;

  /**
   * 保存到表中，当主键有值时则修改，否则插入
   * @param data 各项列和值
   * @param beforeQuery 是否根据id查询有没有数据
   */
  save(data?: { [key: string]: any }, beforeQuery?: boolean): Promise<any>;

  /**
   * 执行插入语句，返回主键
   * @param data 各项列和值
   */
  insert(data?: { [key: string]: any }): Promise<any>;

  /**
   * 执行delete语句
   */
  delete(): Promise<any>;

  /**
   * 执行update语句
   * @param data 各项列和值
   * @param isUpdateBlank 是否更新空值字段
   */
  update(data?: { [key: string]: any }, isUpdateBlank?: boolean): Promise<any>;

  /**
   * 执行分页查询，分页条件手动传入
   * @param limit 限制条数
   * @param offset 跳过条数
   */
  page(limit: number, offset: number): Promise<PageResult>;

  /**
   * 执行select查询
   */
  select(): Promise<any[]>;

  /**
   * 执行selectOne查询
   */
  selectOne(): Promise<any | unknown>;

  /**
   * 查询条数
   */
  count(): Promise<number>;

  /**
   * 查询是否存在
   */
  exists(): Promise<boolean>;
}

declare interface NamedTable {
  properties: Map<string, any>;
  setAttribute(key: string, value: any): void;
  getAttribute(key: string): any;
  getProperties(): Map<string, any>;
  setProperties(properties: Map<string, any>): void;

  /**
   * 逻辑删除
   */
  logic(): NamedTable;

  /**
   * 更新空值
   */
  withBlank(): NamedTable;

  /**
   * 拼接where
   */
  where(): Where;

  /**
   * 设置主键名，update时使用
   * 设置主键名，并设置默认主键值(主要用于insert)
   * @param primary 主键列
   * @param defaultPrimaryValue 默认值
   */
  primary(primary: string, defaultPrimaryValue?: any | Function): NamedTable;

  /**
   * 设置单列的值
   * @param property 列名
   * @param value 值
   */
  column(property: string, value?: any): NamedTable;

  /**
   * 设置查询的列，如`columns('a','b','c')`
   * @param properties 各项列
   */
  columns(...properties: string[]): NamedTable;

  /**
   * 设置要排除的列
   * @param property
   */
  exclude(property: string): NamedTable;

  /**
   * 设置查询的列，如`columns('a','b','c')`
   * @param properties 各项列
   */
  excludes(...properties: string[]): NamedTable;

  /**
   * 拼接`order by xxx asc/desc`
   * @param property 要排序的列
   * @param sort `asc`或`desc`
   */
  orderBy(property: string, sort?: 'asc' | 'desc'): NamedTable;

  /**
   * 拼接`order by xxx desc`
   * @param property 要排序的列
   */
  orderByDesc(property: string): NamedTable;

  /**
   * 拼接`group by`
   * @param properties 要分组的列
   */
  groupBy(...properties: string[]): NamedTable;

  /**
   * 执行插入,返回主键
   * @param data 各项列和值
   */
  insert(data: { [key: string]: any }): Promise<string | number>;

  /**
   * 保存到表中，当主键有值时则修改，否则插入
   * @param data 各项列和值
   * @param beforeQuery 是否根据id查询有没有数据
   * @return 新增返回id 更新返回更新行数
   */
  save(
    data?: { [key: string]: any } | boolean,
    beforeQuery?: boolean
  ): Promise<number | any>;

  /**
   * 执行分页查询，分页条件手动传入
   * @param limit 限制条数
   * @param offset 跳过条数
   */
  page(limit: number, offset: number): Promise<PageResult>;

  /**
   * 执行update语句
   * @param data 各项列和值
   * @param isUpdateBlank 是否更新空值字段
   */
  update(
    data: { [key: string]: any },
    isUpdateBlank?: boolean
  ): Promise<number>;

  /**
   * 查询条数
   */
  count(): Promise<number>;

  /**
   * 判断是否存在
   */
  exists(): Promise<boolean>;

  /**
   * 查询List，并传入变量信息
   */
  select(): Promise<any[]>;

  /**
   * 执行`selectOne`查询
   */
  selectOne(): Promise<any>;

  /**
   * 批量插入
   * @param collection 对象数据
   * @param batchSize 批量
   */
  batchInsert(
    collection: { [key: string]: any }[],
    batchSize?: number
  ): Promise<number>;
}

declare interface PageResult {
  total: number;
  list: any[];
}

/**
 * 事务处理器
 */
declare interface Transaction {
  /**
   * 回滚事务
   */
  rollback: () => Promise<void>;
  /**
   * 提交事务
   */
  commit: () => Promise<void>;
}

/**
 * 数据源模块
 */
declare interface SQLModule {
  /**
   * 设置缓存
   * @param cacheName 缓存名称
   * @param ttl 过期时间 单位为秒
   */
  cache(cacheName: string, ttl?: number): this;

  /**
   * 删除缓存
   * @param cacheName 缓存名称
   * @param matchStart 是否匹配开头为缓存名称的所有key 默认true
   */
  deleteCache(cacheName: string, matchStart?: boolean): Promise<void>;

  /**
   * SQL查询
   * @param sqlOrXml `SQL`语句或`xml`
   * @param params 变量信息 `{'a': 1}`
   */
  select(sqlOrXml: string, params?: { [key: string]: any }): Promise<any[]>;

  /**
   * SQL更新
   * @param sqlOrXml `SQL`语句或`xml`
   * @param params 变量信息 `{'a': 1}`
   */
  update(sqlOrXml: string, params?: { [key: string]: any }): Promise<any[]>;

  /**
   * SQL插入
   * @param sqlOrXml `SQL`语句或`xml`
   * @param params 变量信息 `{'a': 1}`
   * @return 返回ID
   */
  insert(
    sqlOrXml: string,
    params?: { [key: string]: any }
  ): Promise<string | number>;

  /**
   * 查询int值，适合单行单列int的结果
   * @param sqlOrXml `SQL`语句或`xml`
   * @param params 变量信息 `{'a': 1}`
   */
  selectInt(sqlOrXml: string, params?: { [key: string]: any }): Promise<number>;

  /**
   * 查询单条结果，查不到返回null
   * @param sqlOrXml `SQL`语句或`xml`
   * @param params 变量信息 `{'a': 1}`
   */
  selectOne(sqlOrXml: string, params?: { [key: string]: any }): Promise<any>;

  /**
   * 查询单行单列的值
   * @param sqlOrXml `SQL`语句或`xml`
   * @param params 变量信息 `{'a': 1}`
   */
  selectValue(sqlOrXml: string, params?: { [key: string]: any }): Promise<any>;

  /**
   * 执行分页查询，并传入变量信息，分页`SQL`countSqlOrXml
   * @param countSqlOrXml count语句
   * @param sqlOrXml 查询语句
   * @param limit 限制条数
   * @param offset 跳过条数
   * @param params 变量信息
   */
  page(
    countSqlOrXml: string,
    sqlOrXml: string,
    limit: number,
    offset: number,
    params?: { [key: string]: any }
  ): Promise<PageResult>;

  /**
   * 执行分页查询，分页条件手动传入
   * @param sqlOrXml 查询语句
   * @param limit 限制条数
   * @param offset 跳过条数
   * @param params 变量信息
   */
  page(
    sqlOrXml: string,
    limit: number,
    offset: number,
    params?: { [key: string]: any }
  ): Promise<PageResult>;

  /**
   * 批量执行操作，返回受影响的行数
   * @param sql `SQL`语句 或者多条sql
   * @param args 变量信息
   * @param batchSize 每次多少条
   */
  batchUpdate(sql: string, args: any[][], batchSize?: number): Promise<number>;

  /**
   * 批量执行操作，返回受影响的行数
   * @param sqls `SQL`语句 或者多条sql
   */
  batchUpdate(sqls: string[]): Promise<number>;

  /**
   * 指定table，进行单表操作
   * @param tableName 表名称
   */
  table(tableName: string): NamedTable;

  /**
   * 手动事务
   */
  transaction(): Promise<Transaction>;

  /**
   * 自动事务
   * @param _function 回调函数，如：async() => {....}
   */
  transaction(_function: () => Promise<any>): Promise<any>;
}

/**
 * 数据上下文
 */
declare const db: SQLModule;
