import type { FieldsInfo, JoinTable, WhereCondition } from '@/types/model';
import { client, isType, type FieldType, type App, type Layout } from './kintone-rest-api-client';
import type { DropdownItem } from 'kintone-ui-component';

export const EMPTY_OPTION = {
  value: '',
  label: '--------',
} as DropdownItem;

export const getEmptyWhereCondition = () => ({ field: '', condition: '', data: '' }) as WhereCondition;
export const getEmptyOnCondition = () => ({ leftField: '', rightField: '' });
export const getEmptyFieldsMapping = () => ({ leftField: '', rightField: '' });

export function createEmptyJoinTable(id = Number(new Date())) {
  return resetTable({ id, app: '' } as JoinTable);
}

export function resetTable(table: JoinTable) {
  table.table = '';
  return resetConditions(table);
}

export function resetConditions(table: JoinTable) {
  table.onConditions = [getEmptyOnCondition()];
  table.fieldsMapping = [getEmptyFieldsMapping()];
  table.whereConditions = [getEmptyWhereCondition()];
  return table;
}

const LIMIT = 100; // 每次请求的最大应用数量
export const loadApps = async (offset = 0, _apps: DropdownItem[] = []): Promise<DropdownItem[]> => {
  const { apps } = await client.app.getApps({ limit: LIMIT, offset });
  const allApps: DropdownItem[] = [
    ..._apps,
    ...apps.map((app: App) => ({ value: app.appId, label: app.name + '（ID: ' + app.appId + '）' })),
  ];
  if (apps.length === LIMIT) {
    return loadApps(offset + LIMIT, allApps);
  }
  allApps.sort((a, b) => Number(b.value) - Number(a.value));
  allApps.unshift(EMPTY_OPTION);
  return allApps;
};

export const loadAppFieldsAndLayout = async (appId: string | number = kintone.app.getId() as number) => {
  return {
    fields: (await client.app.getFormFields({ app: appId })).properties,
    layout: (await client.app.getFormLayout({ app: appId })).layout,
  } as FieldsInfo;
};

type Param = { subTableCode?: string; filterType?: FieldType; defaultLabel?: string };
export const getFieldsDropdownItems = (
  { fields, layout }: FieldsInfo,
  { subTableCode, filterType, defaultLabel }: Param = {},
) => {
  // get used field codes
  let fieldOrder: string[];
  let fieldMap = fields;
  if (subTableCode) {
    const subTableFields = layout.find((each) => each.type === 'SUBTABLE' && each.code === subTableCode) as any;
    fieldOrder = subTableFields?.fields.map((field: { code: string }) => field.code) || [];
    const subTableFieldMap = fieldMap[subTableCode] as { fields: Record<string, any> } | undefined;
    fieldMap = subTableFieldMap?.fields || {};
  } else {
    fieldOrder = extractNoSubTableFields(layout);
  }

  // create labels
  const labels = [
    {
      value: EMPTY_OPTION.value,
      label: defaultLabel || EMPTY_OPTION.label,
    },
  ];
  return fieldOrder.reduce((acc, fieldCode) => {
    const field = fieldMap[fieldCode];
    if (!fieldCode || (filterType && !isType[filterType](field))) return acc;
    acc.push({
      value: fieldCode,
      label: field.label + '（FC: ' + fieldCode + '）',
    });
    return acc;
  }, labels);
};

export const getTableFieldsDropdownItems = ({ fields }: FieldsInfo, filterType?: FieldType) => {
  return Object.keys(fields).reduce(
    (acc, fieldCode) => {
      const field = fields[fieldCode];
      if (filterType && !isType[filterType](field)) return acc;
      acc.push({
        value: fieldCode,
        label: field.label + '（FC: ' + fieldCode + '）',
      });
      return acc;
    },
    [EMPTY_OPTION],
  );
};

const extractNoSubTableFields = (layout: Layout) => {
  return layout.reduce((acc, each) => {
    if (each.type === 'SUBTABLE') {
      return acc;
    } else if (each.type === 'ROW') {
      acc.push(...each.fields.map((field: any) => field.code));
    } else if (each.type === 'GROUP') {
      acc.push(...extractNoSubTableFields(each.layout));
    }
    return acc;
  }, [] as string[]);
};

// if (isType.SUBTABLE(field)) {
//   console.log(field.fields);
// }
