import axios from "axios";
import qs from "qs";
import { useStorage } from "@vueuse/core";
import { App } from "vue";

const baseURL = import.meta.env.VITE_API_BASE_URL;
const axiosInstance = axios.create({
    baseURL,
    headers: { "Accept-Language": "en-US,en" },
});

const token = useStorage("appToken", "", localStorage);
if (token.value) {
    axiosInstance.defaults.headers.common["Authorization"] =
        "Bearer " + token.value;
}

axiosInstance.interceptors.response.use(
    function (response) {
        return response;
    },
    function (error) {
        let errorData = {};
        if (!error.response) {
            errorData = {
                error: "Network Error",
            };
        } else {
            errorData = error.response.data;
        }
        if (typeof errorData != "object") {
            errorData = {
                error: "Request failed: " + error.response.status,
            };
        }
        return Promise.reject(errorData);
    }
);

const http = {
    install: (app: App) => {
        app.config.globalProperties.$http = http;
        app.provide("http", app.config.globalProperties.$http);
    },
    token,
    baseURL,
    resolve(path: string) {
        let base = baseURL;
        if (!baseURL.startsWith("http")) {
            base = new URL(baseURL, window.location.origin).href;
        }
        return new URL(path, base).href;
    },
    setToken(_token?: string | null) {
        token.value = _token;
        if (_token) {
            axiosInstance.defaults.headers.common["Authorization"] =
                "Bearer " + _token;
        } else {
            axiosInstance.defaults.headers.common["Authorization"] = null;
        }
    },
    async login(phone: string, password: string): Promise<any> {
        const { data: token } = await axiosInstance.post(
            "/auth/login",
            qs.stringify({ phone, password })
        );
        this.setToken(token);
    },
    get(url: string, params?: any): Promise<any> {
        return new Promise((resolve, reject) => {
            axiosInstance
                .get(url, { params, withCredentials: true })
                .then((res) => {
                    resolve(res.data);
                })
                .catch((e) => {
                    reject(e);
                });
        });
    },
    delete(url: string, params?: any): Promise<any> {
        return new Promise((resolve, reject) => {
            axiosInstance
                .delete(url, { params, withCredentials: true })
                .then((res) => {
                    resolve(res.data);
                })
                .catch((e) => {
                    reject(e);
                });
        });
    },
    post(url: string, body: any, options?: any): Promise<any> {
        options = options || {};
        body = body || {};
        if (!(body instanceof FormData)) {
            if (options.body !== "json") {
                body = qs.stringify(body);
            }
        }
        return new Promise((resolve, reject) => {
            axiosInstance
                .post(url, body, { withCredentials: true })
                .then((res) => {
                    resolve(res.data);
                })
                .catch((e) => {
                    reject(e);
                });
        });
    },
    put(url: string, body: any, options?: any): Promise<any> {
        options = options || {};
        body = body || {};
        if (!(body instanceof FormData)) {
            if (options.body !== "json") {
                body = qs.stringify(body);
            }
        }
        return new Promise((resolve, reject) => {
            axiosInstance
                .put(url, body, { withCredentials: true })
                .then((res) => {
                    resolve(res.data);
                })
                .catch((e) => {
                    reject(e);
                });
        });
    },
};

export default http;
