import type { AxiosInstance, AxiosRequestConfig } from 'axios';
import axios from 'axios';
import { CONFIG } from 'src/global-config';

const API_CONFIGS = {
  nodesandbox: {
    baseURL: CONFIG.nodesandbox.api, // misal: https://api.yourdomain.com
    name: 'nodesandbox API',
  },
  apiJava: {
    baseURL: CONFIG.apiJava.api,
    portPPH21: CONFIG.apiJava.prot.pph21,
    portCetak: CONFIG.apiJava.prot.cetak,
    AuthUser: CONFIG.apiJava.AuthBesic.username,
    AuthPass: CONFIG.apiJava.AuthBesic.password,
    name: 'java API',
  },
} as const;

const createAxiosInstance = (
  baseURL: string,
  name: string,
  options?: {
    useBasicAuth?: boolean;
    username?: string;
    password?: string;
  }
): AxiosInstance => {
  const instance = axios.create({
    baseURL,
    headers: {
      'Content-Type': 'application/json',
    },
  });

  // Request Interceptor
  instance.interceptors.request.use(
    (config) => {
      // Basic Auth untuk Java API
      if (options?.useBasicAuth && options.username && options.password) {
        const credentials = btoa(`${options.username}:${options.password}`);
        config.headers.Authorization = `Basic ${credentials}`;
      } else {
        // Bearer Token untuk Node API
        const accessToken = localStorage.getItem('jwt_access_token');
        const xToken = localStorage.getItem('x-token');
        if (accessToken && xToken) {
          config.headers.Authorization = `Bearer ${accessToken}`;
          config.headers['x-token'] = xToken;
        }
      }
      return config;
    },
    (error) => Promise.reject(error)
  );

  // Response Interceptor
  instance.interceptors.response.use(
    (response) => response,
    (error) => {
      const message = error?.response?.data?.message || error?.message || 'Something went wrong!';
      console.error(`[${name}] Axios error:`, message);
      return Promise.reject(new Error(message));
    }
  );

  return instance;
};

export const axiosnodesandbox = createAxiosInstance(
  API_CONFIGS.nodesandbox.baseURL,
  API_CONFIGS.nodesandbox.name
);

export const axiosHitung = createAxiosInstance(
  `${API_CONFIGS.apiJava.baseURL}:${API_CONFIGS.apiJava.portPPH21}`,
  API_CONFIGS.apiJava.name,
  {
    useBasicAuth: true,
    username: API_CONFIGS.apiJava.AuthUser,
    password: API_CONFIGS.apiJava.AuthPass,
  }
);

export const axiosCetakPDF = createAxiosInstance(
  `${API_CONFIGS.apiJava.baseURL}:${API_CONFIGS.apiJava.portCetak}`,
  `${API_CONFIGS.apiJava.name} Cetak`,
  {
    useBasicAuth: true,
    username: API_CONFIGS.apiJava.AuthUser,
    password: API_CONFIGS.apiJava.AuthPass,
  }
);

export default axiosnodesandbox;

type FetcherArgs = string | [string, AxiosRequestConfig & { method?: string }];

export const fetcher = async <T = unknown>(args: FetcherArgs): Promise<T> => {
  try {
    const [url, config = {}] = Array.isArray(args) ? args : [args, {}];
    const { method = 'GET', ...restConfig } = config;

    const res = await axiosnodesandbox.request<T>({
      url,
      method,
      ...restConfig,
    });

    return res.data;
  } catch (error) {
    console.error('[sandbox API] Fetcher failed:', error);
    throw error;
  }
};

export const fetcherHitung = async <T = unknown>(args: FetcherArgs): Promise<T> => {
  try {
    const [url, config = {}] = Array.isArray(args) ? args : [args, {}];
    const { method = 'GET', ...restConfig } = config;

    const res = await axiosHitung.request<T>({
      url,
      method,
      ...restConfig,
    });

    return res.data;
  } catch (error) {
    console.error('[Java API] Fetcher failed:', error);
    throw error;
  }
};

export const fetcherCetakPDF = async <T = unknown>(args: FetcherArgs): Promise<T> => {
  try {
    const [url, config = {}] = Array.isArray(args) ? args : [args, {}];
    const { method = 'GET', headers, ...restConfig } = config;

    const res = await axiosCetakPDF.request<T>({
      url,
      method,
      headers: {
        password: '',
        ...headers,
      },
      ...restConfig,
    });

    return res.data;
  } catch (error) {
    console.error('[Java API] Fetcher failed:', error);
    throw error;
  }
};

export const endpoints = {
  pph21: {
    bulanan: {
      list: '/IF_TXR_028/a0',
      delete: '/IF_TXR_028/a0/delete',
      upload: '/IF_TXR_028/a0/upload',
      canceled: '/IF_TXR_028/a0/batal',
    },
    fnlTdkFnl: {
      list: '/IF_TXR_028/21',
      delete: '/IF_TXR_028/21/delete',
      upload: '/IF_TXR_028/21/upload',
      canceled: '/IF_TXR_028/21/batal',
    }
  },
  masterData: {
    kodeNegara: '/sandbox/mst_negara',
    services: '/sandbox/mst_services',
    goods: '/sandbox/mst_goods',
    satuan: '/sandbox/mst_satuan',
    signer: '/sandbox/signer',
    kop_bpnr: '/sandbox/mst_kop_bpnr',
    kop_bpu: '/sandbox/mst_kop_bpu',
    kop_bpsp: '/sandbox/mst_kop_bpsp',
    kop_all: '/sandbox/mst_kop_all',
    mst_kop_21: '/sandbox/mst_kop_21',
    faktur_keterangan: '/sandbox/mst_faktur_keterangan',
    faktur_idtambahan: '/sandbox/mst_faktur_idtambahan',
  },
  hitung: {
    bulanan: '/pph21/v1/hitung/ctas/bulanan',
    harian: '/pph21/v1/hitung/ctas/harian',
    pasal17: '/pph21/v1/hitung/ctas/pasal17',
    pesangon: '/pph21/v1/hitung/ctas/pesangon',
    pensiun: '/pph21/v1/hitung/ctas/pensiun',
    finalTdkFinal: '/bupot21/hitung/final',
    tahunan: '/pph21/v1/hitung/ctas/yearly',
    tahunanA2: 'IF_TXR_055/a2',
  },
  cetak: {
    bulanan: '/report/ctas/bpm',
    finalTidakFinal: '/report/ctas/bp21',
    tahunanA1: '/report/ctas/a1',
  },
} as const;
