import { AppModule } from '@ithinkdt/app'
import { Awaitable, MaybeArray } from '@ithinkdt/common'
import { HttpClient, HttpInterceptor, HttpRequestInit } from '@ithinkdt/common/request'

import '../shims.js'

/** HttpClient Interceptor  */
export declare const interceptor: (options?: {
    language?: ('zh-CN' | 'en-US' | (string & {}) | undefined) | (() => 'zh-CN' | 'en-US' | (string & {}) | undefined)
    onAuthError?: (
        type: 'NOT_VALID_TOKEN_TYPE' | 'REQUEST_TOKEN_ERROR' | 'ACCOUNT_FREEZE_ERROR' | 'LOGIN_EXPIRED',
        error: Error,
    ) => void
}) => HttpInterceptor

/** Options for {@link cloud} */
export interface CloudOptions {
    /** 自定义 HttpClient  */
    request?: HttpClient | undefined
}

/**
 * cloud 服务
 * @param sysServerName - 系统服务名
 */
export declare function cloud(sysServerName: string, options?: CloudOptions): {
    /** 获取所有应用 */
    getAllApps: () => Promise<CloudApp[]>
    getAppName: (appCode: string, lang: string) => Promise<string>
    /** 获取前端配置 */
    getFrontConfig: (
        appCode: string,
        /**
         * 是否启用缓存（仅 session 会话中生效）
         * @defaultValue true
         */
        cached?: boolean | string,
        yidaServerName?: string,
    ) => Promise<CloudConfig>
    /** 获取翻译资源 */
    getI18nResources: (appCode: string, lang: string) => Promise<{ [k in string]?: string }>
    /** 图标 */
    getIconData: (id: string) => Promise<string | undefined>
    /** 认证 */
    authenticator: (appCode: string, lang: string) => CloudAuthenticator
}

export default cloud

/** 应用信息 */
export interface CloudApp {
    id: string
    appCode: string
    appName: string
    url: string
    logo: string
}

/** 应用配置信息，可扩展 */
export interface CloudConfig {
    /** 是否开启多页签 */
    multiTab: boolean
    /** 是否开启菜单手风琴模式 */
    menuAccordion: boolean
    /** menu 位置 */
    menuPlacement: 'sidebar' | 'header' | 'split'
    /** logo 位置 */
    logoPlacement: 'sidebar' | 'header'
    /** 多租户 */
    tenant: boolean
    /** 是否支持多语言切换 */
    i18n: boolean
    /** 语言 */
    defaultLanguage: 'zh-CN' | 'en-US' | (string & {})
    /** 支持的语言列表 */
    supportLanguages: DictItem[]
    /** 单点登录 */
    sso: false | SSOConfig
    /** 渲染水印 */
    watermark:
        | false
        | ((user: UserInfo) => {
            content: string
            fontFamily?: string
            fontSize?: number
            fontStretch?: string
            fontStyle?: 'normal' | 'italic' | 'oblique' | `oblique ${number}deg`
            fontVariant?: string
            fontWeight?: number
            height?: number
            lineHeight?: number
            rotate?: number
            textAlign?: 'left' | 'right' | 'center'
            width?: number
            zIndex?: number
            cross?: boolean
            xGap?: number
            yGap?: number
            selectable?: boolean
            debug?: boolean
            yOffset?: number
            xOffset?: number
            image?: string
            imageHeight?: number
            imageWidth?: number
            imageOpacity?: number
            fontColor?: string
            globalRotate?: number
        })
    /** 页脚内容 */
    footer: string | undefined
    /** 是否展示网页颜色模式切换按钮 */
    appearance: boolean
    /** 主题配置，亮色和暗色 */
    theme: {
        [mode in 'light' | 'dark']: Record<
            'vars' | (string & {}),
            Record<string, string | boolean | number | undefined>
        >
    }
    /** 默认请求超时时间 */
    timeout: number | undefined
    /** 消息通知刷新时间间隔 */
    msgInterval: number | undefined

    /** 易搭入口 */
    yidaEntry: string | undefined
}

export interface SSOConfig {
    /** 获取登录地址 */
    getLoginUrl: (redirectUrl?: string) => Awaitable<string>
    /** 登出 */
    getLogoutUrl: (redirectUrl?: string, username?: string, token?: string) => Awaitable<string>
    /** 从 url 解析 token 和 目标地址 */
    parseUrl: (fromUrl: string) => { token: string, search?: string, hash?: string } | undefined
    /** 是否允许不通过 sso 登录 */
    selfLogin: boolean
}

/** 认证工具 */
export interface CloudAuthenticator {
    /** 登录 */
    login: (username: string, password: string) => Promise<string>

    /** 登出 */
    logout: (token: string) => Promise<void>

    /** 获取用户信息 */
    getUserInfo: (token: string) => Promise<UserInfo>

    /** 修改密码 */
    changePwd: (token: string, currentPwd: string, newPwd: string) => Promise<void>

    /** 刷新用户权限 */
    refreshAuth: (token: string) => Promise<string>

    /** 获取模块信息 */
    getUserModules: (token: string) => Promise<UserModule[]>
}

/** 用户信息 */
export interface UserInfo {
    id: string
    /** 用户名 */
    username: string
    /** 昵称 */
    nickname: string
    /** 人名 */
    personName: string
    /** 账号未失效 */
    accountNonExpired: boolean
    /** 账号未被锁定 */
    accountNonLocked: boolean
    /** 证书未失效 */
    credentialsNonExpired: boolean
    /** 数据权限 */
    dataScope: Record<string, 0 | 1 | 2>
    /** 启用状态 */
    enabled: boolean
    /** 电子邮箱 */
    email: string
    /** 手机 */
    phone: string
    /** 租户 id */
    tenantId: string
    /** 所属租户列表 */
    tenantList: TenantItem[] | undefined
}

/** 租户信息 */
export interface TenantItem {
    id: string
    name: string
    shotName?: string | undefined
}

export interface FileInfo {
    id: string
    name: string
    size: number
    type: string
    url: string
    thumbnailUrl: string
    accessRight: 'INTERNAL' | 'PRIVATE' | 'PUBLIC'
    status: 'finished'
}

export declare function useCloud(options: { request?: HttpClient, sysServerName?: string, mcServerName?: string, fileServerName?: string }): {
    /** tenant */
    changeTenant: (tenantId: string) => Promise<string>
    /** logo */
    renderLogo: () => import('vue').VNodeChild
    /** 图标 */
    getIconRender: (id: string) => ((placeholder?: import('vue').VNodeChild) => import('vue').VNodeChild)
    /** 图标 */
    getIconData: (id: string) => Promise<string | undefined>
    /** 消息 */
    notification: CloudNotification
    /** 字典 */
    getDictByTypes: (types: string[], lang?: string, appCode?: string) => Promise<Record<string, DictItem[] | undefined>>
    /** 国际化 */
    getModuleResources: (lang: string, moduleCode: string, appCode?: 'ALL' | string & {}, contentCode?: string) => Promise<Record<string, string>>
    saveResources: (moduleCode: string, contentCode: string, resources: Record<string, string | undefined>, appCode: string) => Promise<void>
    deleteResources: (moduleCode: string, contentCode: string, appCode: string) => Promise<void>
    getResources: (moduleCode: string, contentCode: string, appCode: string) => Promise<Record<string, string>>
    /** 系统参数 */
    getSysParams: <T extends object = Record<string, unknown>>(group: string) => Promise<T>

    /** file */
    removeFile: (fileId: string) => Promise<void>
    getFileInfos: (fileIds: string[]) => Promise<FileInfo[]>
    previewFileUrl: (fileId: string, credentials?: boolean) => string
    downloadFileUrl: (fileId: string, credentials?: boolean) => string
    uploadFile: (file: File, options?: {
        fileName?: string | undefined
        filePath?: string | undefined
        accessRight?: 'INTERNAL' | 'PRIVATE' | 'PUBLIC' | undefined
        onProgress?: ((percent: number) => void) | undefined
    }) => Promise<string>

    /** user org dept */
    getUserGroups?: (() => Promise<{ code: string, name: string }[]>) | undefined
    getUsersByGroup?: ((code: string) => Promise<{ username: string, nickname: string }[]>) | undefined
    getUsersByOrg?: ((code: string) => Promise<{ username: string, nickname: string }[]>) | undefined
    getUsersByUsername?: ((usernames?: string[]) => Promise<{ username: string, nickname: string }[]>) | undefined
    getOrgsByCode?: (codes?: string[]) => Promise<OrgTreeNode[]>

    /** 获取服务器时间 */
    getServerTimestamp: () => Promise<number>
}

interface OrgTreeNode {
    code: string
    name: string
    children?: OrgTreeNode[] | undefined
}

/** 消息工具 */
export interface CloudNotification {
    getUnreadCount: () => Promise<number>
    getPage: (
        type: 'all' | 'unread',
        page: number,
        size: number,
        searchtext?: string,
    ) => Promise<{
        records: {
            key: string
            title: string
            content: () => import('vue').VNodeChild
            date: number
            status: 'read' | 'unread'
            link?: string
        }[]
        total: number
    }>
    markRead: (keys: string[]) => Promise<void>
    markDelete: (keys: string[]) => Promise<void>
}

/** 字典项 */
export interface DictItem {
    value: string
    label: string
    remark?: string
    labelMap: Record<string, string | undefined>
}

/** 图标工具 */
export interface CloudIcon {
    getData: (id: string) => Promise<string | undefined>
    getRender: (id: string) => ((placeholder?: import('vue').VNodeChild) => import('vue').VNodeChild)
}

export type UserModule = AppModule

export declare interface CloudResponse<T = unknown> {
    status: boolean
    code: number
    message: string
    data: T
}

/** 初始化 */
export declare function setup(options: { request: HttpClient }): void

export type ApiOptionsString = `${'get' | 'delete' | 'post' | 'put'}` | `${'post' | 'put'}|${HttpRequestInit['requestType']}`
export type ApiString = `${ApiOptionsString}: ${string}`

/**
 * id 字段类型
 */
type ID = string

/**
 * 创建增删改查接口
 *
 * @param resource - 资源名称
 */
export declare function createCrudApi<
    Entity extends { id: ID },
    ReturnEntity extends boolean = false,
    DetailEntity extends { id: ID } = Entity,
    FilterParams extends {} = { [K in keyof Entity]?: Entity[K] | undefined | null },
    CreateParams extends { id?: undefined | null } = Omit<Entity, 'id' | 'createDate' | 'createUser' | 'updateDate' | 'updateUser' | 'deleted'> & { id?: undefined | null },
    UpdateParams extends { id: ID } = Omit<Entity, 'createDate' | 'createUser' | 'updateDate' | 'updateUser' | 'deleted'>,
>(
    resource: string | {
        resource?: string | undefined
        list?: ApiString | undefined
        page?: ApiString | undefined
        get?: ApiString | undefined
        post?: ApiString | undefined
        put?: ApiString | undefined
        save?: ApiString | undefined
        delete?: ApiString | undefined
    },
): {
    list(
        this: void,
        params: { filter?: FilterParams | undefined, sortField?: string | undefined, sortOrder?: 'asc' | 'desc' | undefined },
    ): Promise<Entity[]>
    page(
        this: void,
        params: {
            pageSize?: number | undefined
            currentPage?: number | undefined
            filter?: FilterParams | undefined
            sortField?: string | undefined
            sortOrder?: 'asc' | 'desc' | undefined
        },
    ): Promise<{ total: number, records: Entity[] }>
    get(this: void, id: ID): Promise<DetailEntity | undefined>
    post(this: void, entity: CreateParams): Promise<ReturnEntity extends true ? Entity : undefined>
    put(this: void, entity: UpdateParams): Promise<ReturnEntity extends true ? Entity : undefined>
    save(this: void, entity: CreateParams | UpdateParams): Promise<ReturnEntity extends true ? Entity : undefined>
    delete(this: void, id: MaybeArray<ID>): Promise<void>
}
