import type { FieldsInfo } from '@/types/model';
import { isType, type FieldType, type OneOf } from './kintone-rest-api-client';
import { getFieldObj } from './helper';

// conditionValue = '' | 'eq' | 'ne'
// conditionItem  = { value: 'eq', label: '=（等しい）', type: 'input', func: (a: string, b: string) => a === b }
//                = conditionMap[conditionValue]
export type ConditionValue = '' | 'eq' | 'ne' | 'le' | 'lt' | 'gt' | 'ge' | 'contains' | 'not_contain';

type ConditionItem = {
  value: ConditionValue;
  label: string | ((field: OneOf) => string);
  type: ComponentType; // | ((field: OneOf) => ComponentType);
};

export const conditionList: ConditionItem[] = [
  { value: 'eq', label: '=（等しい）', type: 'input' },
  { value: 'ne', label: '≠ （等しくない）', type: 'input' },
  { value: 'le', label: (field) => isDateTimeType(field) ? '≦ （以前）' : '≦ （以下）', type: 'input' },
  { value: 'lt', label: '< （より前）', type: 'input' },
  { value: 'gt', label: '> （より後）', type: 'input' },
  { value: 'ge', label: (field) => isDateTimeType(field) ? '≧ （以降）' : '≧ （以上）', type: 'input' },
  { value: 'contains', label: '次のいずれかを含む', type: 'input' },
  { value: 'not_contain', label: '次のいずれも含まない', type: 'input' },
];

// search from conditionList
// conditionItem = conditionMap[conditionValue]
export const conditionMap: Record<ConditionValue, ConditionItem> = conditionList.reduce(
  (map, item) => {
    map[item.value] = item;
    return map;
  },
  {} as Record<ConditionValue, ConditionItem>,
);

type FieldConditions = Partial<Record<FieldType, ConditionValue[]>>;

const textCondition: ConditionValue[] = ['eq', 'ne', 'contains', 'not_contain'];
const numberCondition: ConditionValue[] = ['eq', 'ne', 'le', 'ge'];
const timeCondition: ConditionValue[] = ['eq', 'ne', 'le', 'lt', 'ge', 'gt'];
const containsCondition: ConditionValue[] = ['contains', 'not_contain'];

// FieldType -> ConditionValue[]
const fieldConditions: FieldConditions = {
  SINGLE_LINE_TEXT: textCondition,
  MULTI_LINE_TEXT: containsCondition,
  RICH_TEXT: containsCondition,
  NUMBER: numberCondition,
  CHECK_BOX: containsCondition,
  RADIO_BUTTON: containsCondition,
  DROP_DOWN: containsCondition,
  MULTI_SELECT: containsCondition,
  USER_SELECT: containsCondition,
  ORGANIZATION_SELECT: containsCondition,
  GROUP_SELECT: containsCondition,
  LINK: textCondition,
  CALC: numberCondition,

  TIME: timeCondition,
  DATE: timeCondition,
  DATETIME: timeCondition,
  CREATED_TIME: timeCondition,
  CREATOR: containsCondition,
  UPDATED_TIME: timeCondition,
  MODIFIER: containsCondition,
  RECORD_NUMBER: numberCondition,
} as const;

// fieldCode -> conditionList: ConditionItem[]
export const getAvailableCondition = (fieldCode: string, fieldsInfo: FieldsInfo, subTableCode: string | '') => {
  if (!fieldCode || !fieldsInfo.fields) return;
  const fieldObj = getFieldObj(fieldCode, fieldsInfo, '');
  if (!fieldObj) return;
  const conditions = fieldConditions[fieldObj.type] || textCondition; // TODO a fallback here
  return conditions.map((condition) => {
    const res = {...conditionMap[condition]}
    res.label = typeof res.label === 'function' ? res.label(fieldObj) : res.label;
    return res;
  });
};

const component = {
  input: 'kuc-text',
  select: 'kuc-combobox',
  time: 'kuc-time',
  date: 'date',
  datetime: 'datetime',
};

export const isDateTimeType = (field: OneOf) => {
  return field.type in dateTimeComponent;
}

const dateTimeComponent: Partial<Record<FieldType, ComponentType>> = {
  TIME: 'time',
  DATE: 'date',
  DATETIME: 'datetime',
  CREATED_TIME: 'datetime',
  UPDATED_TIME: 'datetime',
}

export type ComponentType = keyof typeof component;
export const getComponent = (value: ConditionValue, fieldObj: OneOf) => {
  if (!value) return;
  const condition = conditionMap[value].type;
  return component[typeof condition === 'function' ? condition(fieldObj) : condition];
};
