import type { ProColumns } from '@ant-design/pro-table';
import type { ProFieldValueType } from '@ant-design/pro-utils';
import { getEnumSelectOptions } from './tools';
import moment from 'moment';

interface ColumnBuilder {
  readonly build: (field: Api.SingleTableField) => ProColumns<any>[];
}

class DefaultBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const column: ProColumns<any> = {
      title: field.name,
      dataIndex: field.code.split('.'),
      valueType: field.valueType as ProFieldValueType,
      hideInSearch: field.hideInSearch,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    return [column];
  };
}

class TextBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const column: ProColumns<any> = {
      title: field.name,
      dataIndex: field.code.split('.'),
      valueType: 'text',
      hideInSearch: field.hideInSearch,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    return [column];
  };
}

class BooleanSelectBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const column: ProColumns<any> = {
      title: field.name,
      dataIndex: field.code.split('.'),
      valueType: 'select',
      valueEnum: {
        true: { text: '是' },
        false: { text: '否' },
      },
      hideInSearch: field.hideInSearch,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    return [column];
  };
}

class IdEntityBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const column: ProColumns<any> = {
      title: field.name,
      dataIndex: [...field.code.split('.'), 'id'],
      valueType: 'text',
      hideInSearch: field.hideInSearch,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    return [column];
  };
}

class KeysEntityBuilder implements ColumnBuilder {
  readonly build = () => {
    return [];
  };
}

class IdEnumBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const column: ProColumns<any> = {
      title: field.name,
      dataIndex: [...field.code.split('.'), 'id'],
      valueType: 'text',
      hideInSearch: field.hideInSearch,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    return [column];
  };
}

class KeysEnumBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const column: ProColumns<any> = {
      title: field.name,
      dataIndex: [...field.code.split('.'), 'id'],
      valueType: 'select',
      hideInSearch: field.hideInSearch,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
      request: async () => {
        return await getEnumSelectOptions(field.dataType.substring(1), field.keys, field.display);
      },
    };
    return [column];
  };
}

class DateRangeBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const columnTable: ProColumns<any> = {
      title: field.name,
      dataIndex: [...field.code.split('.')],
      valueType: 'date',
      hideInSearch: true,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    const columnSearch: ProColumns<any> = {
      title: field.name,
      dataIndex: [...field.code.split('.')],
      valueType: 'dateRange',
      hideInSearch: field.hideInSearch,
      hideInTable: true,
    };
    return [columnTable, columnSearch];
  };
}

class DateTimeRangeBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const columnTable: ProColumns<any> = {
      title: field.name,
      dataIndex: [...field.code.split('.')],
      valueType: 'dateTime',
      hideInSearch: true,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    const columnSearch: ProColumns<any> = {
      title: field.name,
      dataIndex: [...field.code.split('.')],
      valueType: 'dateTimeRange',
      hideInSearch: field.hideInSearch,
      hideInTable: true,
      initialValue: [
        moment(moment().subtract(1, 'day').format('YYYY-MM-DD')).format('YYYY-MM-DD HH:mm:ss'),
        moment(moment().add(1, 'day').format('YYYY-MM-DD')).format('YYYY-MM-DD HH:mm:ss'),
      ],
      colSize: 2,
    };
    return [columnTable, columnSearch];
  };
}

class DigitBuilder implements ColumnBuilder {
  readonly build = (field: Api.SingleTableField) => {
    const column: ProColumns<any> = {
      title: field.name,
      dataIndex: field.code.split('.'),
      valueType: 'digit',
      hideInSearch: field.hideInSearch,
      hideInTable: field.hideInTable,
      width: field.width,
      colSize: field.colSize,
    };
    return [column];
  };
}

class ColumnBuilderManagerClz {
  readonly map: Map<string, ColumnBuilder> = new Map([
    ['default', new DefaultBuilder()],
    ['text.string', new TextBuilder()],
    ['text.id', new TextBuilder()],
    ['select.boolean', new BooleanSelectBuilder()],
    ['id.entity', new IdEntityBuilder()],
    ['keys.entity', new KeysEntityBuilder()],
    ['id.enum', new IdEnumBuilder()],
    ['keys.enum', new KeysEnumBuilder()],
    ['dateRange.date', new DateRangeBuilder()],
    ['dateTimeRange.datetime', new DateTimeRangeBuilder()],
    ['digit.integer', new DigitBuilder()],
    ['digit.long', new DigitBuilder()],
    ['digit.decimal', new DigitBuilder()],
  ]);
  readonly defaultBuilder = new DefaultBuilder();

  build(singleTable: Api.SingleTable | undefined) {
    const columns: ProColumns<any>[] = [];
    if (singleTable) {
      singleTable.fields.forEach((f) => {
        columns.push(...this.buildField(f));
      });
    }
    return columns;
  }

  private buildField(field: Api.SingleTableField) {
    const builder = this.map.get(field.valueType);
    if (builder) {
      return builder.build(field);
    }
    return this.defaultBuilder.build(field);
  }
}

const columnBuilderManager = new ColumnBuilderManagerClz();

export default columnBuilderManager;
