import Axios, { AxiosInstance, AxiosRequestConfig } from "axios";
import { parseCookies } from "nookies";
import "reflect-metadata";
import { getUserTokens } from "./browser_auth/auth";
import { Config } from "./Config";
import { Content } from "./resources/Content";
import { Contribute } from "./resources/Contribute";
import { Search } from "./resources/Search";
import { API_Config } from "./Types";

export interface IClientArgs {
    org: string;
    token: string;
    rootMapId: string;
    timeout?: number;
    scheme?: string;
    hostname?: string;
    env?: string;
}

const EZD_CLIENT_VERSION = "0.1.0";
const API_VERSION = "v1";

export default class Client {
    public readonly base_url: string;
    public content_axios: AxiosInstance;
    public contribute_axios: AxiosInstance;
    public content: Content;
    public search: Search;
    public contribute: Contribute;

    private content_service_token: string;
    private initial_args: IClientArgs;

    constructor(args: IClientArgs) {
        const {
            org,
            token,
            rootMapId,
            timeout = 3000,
            scheme = "https://",
            hostname = "content.easydita.com",
            env = "latest",
        } = args;
        this.initial_args = args;

        if (!org) {
            throw new Error("easyDITA org not set");
        }
        if (!token) {
            throw new Error("easyDITA token not set");
        }
        if (!rootMapId) {
            throw new Error("easyDITA rootMapId not set");
        }

        this.base_url = `${scheme}${hostname}/org/${org}/env/${env}/map/${rootMapId}/`;
        this.content_service_token = token;

        const config: AxiosRequestConfig = {
            baseURL: this.base_url,
            timeout,
            // withCredentials: true,
            headers: {
                // "X-EZD-Client": "JS/" + EZD_CLIENT_VERSION,
            },
        };

        this.content_axios = Axios.create(config);
        this.content_axios.interceptors.request.use(intercepted_config => {
            if (!intercepted_config.params) {
                intercepted_config.params = {};
            }

            // intercepted_config.headers["Content-Type"] = "application/text";
            intercepted_config.params.token = this.user_token() ? this.user_token() : this.content_service_token;
            return intercepted_config;
        });

        this.contribute_axios = Axios.create(config);
        this.contribute_axios.interceptors.request.use(intercepted_config => {
            if (!intercepted_config.params) {
                intercepted_config.params = {};
            }

            intercepted_config.params.rootMapId = rootMapId;
            intercepted_config.params.token = this.user_token();
            return intercepted_config;
        });

        const portal_config = new Config(this.content_axios);

        this.content = new Content({ axios: this.content_axios, config: portal_config });
        this.search = new Search({ axios: this.content_axios, rootMapId, config: portal_config });
        this.contribute = new Contribute({ axios: this.contribute_axios, config: portal_config });
    }

    public iframe_url() {
        let s = this.base_url;
        s = s.replace("https://", "");
        s = s.replace("http://", "");
        return s;
    }

    public user_token() {
        if (typeof window !== "undefined") {
            return getUserTokens().idToken;
        } else {
            return null;
        }
    }

    public async login() {
        // create an ezd session so the editor will load without asking user to login first
        const response = await this.content_axios.post("/auth");
    }

    public prepare(args) {
        if (args.req) {
            const cookies = parseCookies(args);
            if (args.req.query.portal_auth_token) {
                return new Client({...this.initial_args, token: args.req.query.portal_auth_token});
            }
            if (cookies.portal_auth_token) {
                return new Client({...this.initial_args, token: cookies.portal_auth_token});
            }
        }
        return this;
    }

}
