import { HttpClient } from '../refs/cm-tools'
import { OpResult, logger } from 'mslib';
import { KongService, KongRoute, KongPlugin, KongTarget, KongUpstream } from './ApiModels';

/**
 * Kong管理API
 * @date 2021-06-16 09:29:17
 * @author 吴锋霖
 */
export class AdminApi {

    private apiUrl: string
    private httpClient: HttpClient

    constructor(apiUrl: string) {
        this.apiUrl = apiUrl;
        this.httpClient = new HttpClient();
    }

    async addService(kongService: KongService): Promise<OpResult<KongService>> {
        return await this.addKongObj(`${this.apiUrl}/services`, kongService)
    }

    async addRoute(kongRoute: KongRoute): Promise<OpResult<KongRoute>> {
        return await this.addKongObj(`${this.apiUrl}/routes`, kongRoute)
    }

    async addUpstream(kongUpstream: KongUpstream): Promise<OpResult<KongUpstream>> {
        return await this.addKongObj(`${this.apiUrl}/upstreams`, kongUpstream)
    }

    async addTarget(kongTarget: KongTarget): Promise<OpResult<KongTarget>> {
        return await this.addKongObj(`${this.apiUrl}/upstreams/${kongTarget.upstream.id}/targets`, kongTarget)
    }

    async addPlugin(kongPlugin: KongPlugin): Promise<OpResult<KongPlugin>> {
        return await this.addKongObj(`${this.apiUrl}/plugins/`, kongPlugin)
    }

    async getService(id: string): Promise<OpResult<Array<KongService>>> {
        return await this.getKongObj(`${this.apiUrl}/services/${id}`)
    }

    async getRoute(id: string): Promise<OpResult<Array<KongRoute>>> {
        return await this.getKongObj(`${this.apiUrl}/routes/${id}`)
    }

    async getUpstream(id: string): Promise<OpResult<Array<KongUpstream>>> {
        return await this.getKongObj(`${this.apiUrl}/upstreams/${id}`)
    }

    async listServices(tags: string): Promise<OpResult<Array<KongService>>> {
        return await this.listKongObjs(`${this.apiUrl}/services?tags=${tags}`)
    }

    async listRoutes(tags: string): Promise<OpResult<Array<KongRoute>>> {
        return await this.listKongObjs(`${this.apiUrl}/routes?tags=${tags}`)
    }

    async listUpstreams(tags: string): Promise<OpResult<Array<KongUpstream>>> {
        return await this.listKongObjs(`${this.apiUrl}/upstreams?tags=${tags}`)
    }

    async listTargets(upstream: string): Promise<OpResult<Array<KongTarget>>> {
        return await this.listKongObjs(`${this.apiUrl}/upstreams/${upstream}/targets`)
    }

    async listServicePlugins(serviceId: string): Promise<OpResult<Array<KongPlugin>>> {
        return await this.listKongObjs(`${this.apiUrl}/services/${serviceId}/plugins`)
    }

    async listRoutePlugins(routeId: string): Promise<OpResult<Array<KongPlugin>>> {
        return await this.listKongObjs(`${this.apiUrl}/routes/${routeId}/plugins`)
    }

    async deleteService(id: string): Promise<OpResult<any>> {
        return await this.deleteKongObj(`${this.apiUrl}/services/${id}`)
    }

    async deleteRoute(id: string): Promise<OpResult<any>> {
        return await this.deleteKongObj(`${this.apiUrl}/routes/${id}`)
    }

    async deleteUpstream(id: string): Promise<OpResult<any>> {
        return await this.deleteKongObj(`${this.apiUrl}/upstreams/${id}`)
    }

    async deleteTarget(upstream: string, targetId: string): Promise<OpResult<any>> {
        return await this.deleteKongObj(`${this.apiUrl}/upstreams/${upstream}/targets/${targetId}`)
    }

    private async listKongObjs(url) {
        try {
            const response = await this.httpClient.get(url)
            if (!response) {
                return OpResult.error(`调用KongApi失败 ${url}`)
            }
            if (response.status !== 200) {
                return OpResult.error(`调用KongApi失败 ${url}/${response.status}/${response.statusText}`)
            }
            return OpResult.success('OK', response.data.data)
        } catch (e) {
            return OpResult.error(`调用KongApi异常 ${url} ,error:` + e.message)
        }
    }


    private async getKongObj(url) {
        try {
            const response = await this.httpClient.get(url)
            if (!response) {
                return OpResult.error(`调用KongApi失败 ${url}`)
            }
            if (response.status !== 200) {
                return OpResult.error(`调用KongApi失败 ${url}/${response.status}/${response.statusText}`)
            }
            return OpResult.success('OK', response.data)
        } catch (e) {
            return OpResult.error(`调用KongApi异常 ${url} ,error:` + e.message)
        }
    }


    private async deleteKongObj(url) {
        try {
            const response = await this.httpClient.request({ url, method: 'DELETE' })
            if (!response) {
                return OpResult.error(`调用KongApi失败 ${url}`)
            }
            if (response.status !== 204) {
                return OpResult.error(`调用KongApi失败 ${url}/${response.status}/${response.statusText}`)
            }
            return OpResult.success('OK')
        } catch (e) {
            return OpResult.error(`调用KongApi异常 ${url} ,error:` + e.message)
        }
    }


    private async addKongObj(url: string, obj: any) {
        try {
            const response = await this.httpClient.postJson(url, {}, obj)
            if (!response) {
                return OpResult.error(`调用KongApi失败 ${url}`)
            }
            if (response.status !== 201) {
                return OpResult.error(`调用KongApi失败 ${url}/${response.status}/${response.statusText}`)
            }
            return OpResult.success('OK', response.data)
        } catch (e) {
            logger.error(`调用KongApi异常 ${url}`, e)
            return OpResult.error(`调用KongApi异常 ${url} ,error:` + e.message)
        }
    }


}