import useSWR from 'swr';
import config from './config';

type DbEnc = 'utf8';
type DbType = 'mysql' | 'hive';

export interface IDatasource {
  host: string;
  user: string;
  port: number;
  password: string;
  charset: DbEnc;
  manager: string;
  source: DbType;
  databasename: string;
  datasourcename: string;
  sourcename: string;
}

export interface IDatasourceItem {
  jdbc_url: string;
  jdbc_username: string;
  jdbc_password: string;
  manager: string;
  datasource: DbType;
  database_name: string;
  datasource_name: string;
  id: number;
}

export interface IDatasourceForm {
  jdbc_url: string;
  jdbc_username: string;
  jdbc_password: string;
  database_name: string;
  datasource_name: string;
  datasource: 'mysql' | 'hive';
}

interface IDatasourceResponse {
  datasources?: IDatasourceItem[];
  loading: boolean;
  error?: any;
  refresh: () => void;
}

export type ITableData = Record<string, Record<string, any>>;

export const useDatasourceList = (manager: string): IDatasourceResponse => {
  const endpoint = config.endpoint;
  // const item = encodeURIComponent(manager);
  // const url = `${endpoint}/jpt/item=${item}`;
  const url = `${endpoint}/jpt/datasource/`;
  const { data, error, mutate } = useSWR(url, (...args) =>
    fetch(...args).then(res => res.json())
  );
  return {
    datasources: data?.data.items,
    loading: !error && !data,
    error: error || data?.code !== 200,
    refresh: mutate
  };
};

export const setDatasource = async (
  datasource: IDatasourceForm
): Promise<string> => {
  const endpoint = config.endpoint;
  const url = `${endpoint}/jpt/datasource`;
  try {
    const resp = await fetch(url, {
      method: 'post',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...datasource, comments: 'test' })
    });
    if (!resp.ok) {
      return 'error';
    }
    const data = await resp.text();
    return data;
  } catch (e) {
    console.error(e);
    return 'error';
  }
};

export const textDatasource = async (
  datasource: IDatasourceForm
): Promise<string> => {
  const endpoint = config.endpoint;
  const url = `${endpoint}/jpt/datasource/test`;
  try {
    const resp = await fetch(url, {
      method: 'post',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...datasource, comments: 'test' })
    });
    if (!resp.ok) {
      return 'error';
    }
    const data = await resp.json();
    return data.data;
  } catch (e) {
    console.error(e);
    return 'error';
  }
};

export const fetchTables = async (
  ds_id: number
): Promise<'error' | string[]> => {
  const endpoint = config.endpoint;
  const url = `${endpoint}/jpt/datasource/table_names?ds_id=${ds_id}`;
  try {
    const resp = await fetch(url, { method: 'post' });
    if (!resp.ok) {
      return 'error';
    }
    const data = await resp.json();
    if (data.code !== 200) {
      return 'error';
    }
    return data.data;
  } catch (e) {
    console.error(e);
    return 'error';
  }
};

export const fetchTableContent = async (
  ds: IDatasourceItem,
  t: string
): Promise<ITableData | 'error'> => {
  const endpoint = config.endpoint;
  const url = `${endpoint}/jpt/datasource/preview?ds_id=${ds.id}&table_name=${t}`;
  try {
    const resp = await fetch(url, { method: 'post' });
    if (!resp.ok) {
      return 'error';
    }
    const data = await resp.json();
    if (data.code !== 200) {
      return 'error';
    }
    const formatData = {} as ITableData;
    data.data.header.map((col: string | number, index: number) => {
      formatData[col] = data.data.content.map((row: any[]) => row[index]);
    });
    return formatData;
  } catch (e) {
    console.error(e);
    return 'error';
  }
};

export const fetchTableSchema = async (
  ds: IDatasourceItem,
  t: string
): Promise<ITableData | 'error'> => {
  const endpoint = config.endpoint;
  const url = `${endpoint}/jpt/datasource/table_schema?ds_id=${ds.id}&table_name=${t}`;
  try {
    const resp = await fetch(url, { method: 'post' });
    if (!resp.ok) {
      return 'error';
    }
    const data = await resp.json();
    if (data.code !== 200) {
      return 'error';
    }
    const formatData = {} as ITableData;
    const orders = [] as number[];
    const fields = [] as string[];
    const attributes = [] as string[];
    data.data.forEach((item: any, index: number) => {
      const [field, attribute] = item.split(':');
      orders.push(index + 1);
      fields.push(field);
      attributes.push(attribute);
    });
    formatData['序号'] = orders;
    formatData['字段'] = fields;
    formatData['属性'] = attributes;
    return formatData;
  } catch (e) {
    console.error(e);
    return 'error';
  }
};
