import React from 'react';
import {
  FieldDataType,
  ModelType,
  I18N_T,
  ModelsFieldsTypeMap,
  convertPrismaDecimal,
} from '@gadmin2n/react-common';
import {
  TextField,
  DateField,
  FilterDropdown,
  ImageField,
  FileField,
  NumberField,
  BooleanField,
  EmailField,
  UrlField,
  ShowButton,
  TagField,
} from '@refinedev/antd';
import { CheckCircleTwoTone, CloseCircleTwoTone } from '@ant-design/icons';
import { FilterDropdownProps } from 'antd/lib/table/interface';
import { Select, Table, Space, SelectProps, Tooltip, Typography } from 'antd';
import {
  CrudSorting,
  CrudFilters,
  unionFilters,
  getDefaultSortOrder,
  getDefaultFilter,
  stringifyTableParams,
} from '@refinedev/core';
import { DefaultOptionType } from 'antd/es/select';
import { ModelConfig } from 'generated/types/config.types';
import { agentAttrs } from '../components/agentPanel/agentAttributes';
import dayjs from 'dayjs';

export function getTableParams(filters: Record<string, string> = {}) {
  return stringifyTableParams({
    pagination: { pageSize: 10, current: 1 },
    sorters: [],
    filters: Object.entries(filters).map(([field, value]) => ({
      field,
      operator: 'eq',
      value: encodeURIComponent(value),
    })),
  });
}

/**
 * Context for table column rendering
 */
export interface TableColumnContext {
  resourceName: string;
  t: I18N_T;
  model: ModelType;
  modelsEnum: Record<string, Record<string, string>>;
  modelsMap: ModelsFieldsTypeMap;
  tableConfig: ModelConfig['table'];
  sorter: CrudSorting | undefined;
  filters: CrudFilters | undefined;
  relationSelectProps: Record<
    string,
    SelectProps<{ value: string; label: string }, DefaultOptionType>
  >;
}

/**
 * Parameters for getTableColumn function
 */
export interface GetTableColumnParams {
  col: FieldDataType;
  context: TableColumnContext;
}

/**
 * Get table column configuration for a field
 * @deprecated Use the new object parameter version: getTableColumnV2
 */
export function getTableColumn(
  col: FieldDataType,
  resourceName: string,
  t: I18N_T,
  model: ModelType,
  modelsEnum: Record<string, Record<string, string>>,
  modelsMap: ModelsFieldsTypeMap,
  tableConfig: ModelConfig['table'],
  sorter: CrudSorting | undefined,
  filters: CrudFilters | undefined,
  relationSelectProps: Record<
    string,
    SelectProps<{ value: string; label: string }, DefaultOptionType>
  >,
) {
  return getTableColumnV2({
    col,
    context: {
      resourceName,
      t,
      model,
      modelsEnum,
      modelsMap,
      tableConfig,
      sorter,
      filters,
      relationSelectProps,
    },
  });
}

/**
 * Get table column configuration for a field (new object parameter version)
 */
export function getTableColumnV2({ col, context }: GetTableColumnParams) {
  const {
    resourceName,
    t,
    model,
    modelsEnum,
    modelsMap,
    tableConfig,
    sorter,
    filters,
    relationSelectProps,
  } = context;

  const { type: fieldType, args } = col.uiType.formItem;
  const fieldName = col.name;
  const props: any = {
    dataIndex: fieldName.includes('.') ? fieldName.split('.') : fieldName,
    key: fieldName,
    title: t(`resources.${resourceName}.fields.${fieldName}`, fieldName),
    render: (value: any) => {
      // 兜底：未识别 fieldType 但 value 是普通对象，stringify 避免渲染崩溃
      if (
        typeof value === 'object' &&
        value !== null &&
        !React.isValidElement(value)
      ) {
        return <TextField value={JSON.stringify(value)} />;
      }
      return <TextField value={value} />;
    },
  };

  if (col.kind === 'object' && !col.isList && !fieldName.includes('.')) {
    const entityName = model[fieldName]?.type || '';
    props.dataIndex = [fieldName, 'id'];
    props.key = `${fieldName}.id`;
    props.title = t(
      `resources.${resourceName}.fields.${fieldName}`,
      t(`resources.${entityName.toLowerCase()}.name`, entityName),
    );
    props.render = (_: any, record: any) =>
      record?.[fieldName]?.id !== undefined ? (
        <ShowButton
          icon={false}
          type="link"
          size="small"
          resource={entityName.toLowerCase()}
          recordItemId={record[fieldName].id}
        >
          {
            record[fieldName][
              modelsMap[entityName]?.meta?.nameKeys?.[0] || 'id'
            ]
          }
        </ShowButton>
      ) : null;
  } else if (fieldName.startsWith('_count.')) {
    const entityName = model[fieldName.split('.')[1]]?.type || '';
    props.title = t(
      `resources.${resourceName}.fields.${fieldName}`,
      'Count ' + t(`resources.${entityName.toLowerCase()}.name`, entityName),
    );
  } else if (fieldType === 'DateTime') {
    props.render = (value: any) => {
      return <DateField value={value} format="YYYY-MM-DD HH:mm:ss" />;
    };
  } else if (['Int', 'BigInt', 'Float', 'Decimal'].includes(fieldType)) {
    props.render = (value: any) => {
      // Handle Prisma Decimal objects (which have {s, e, d} keys from decimal.js)
      const displayValue = convertPrismaDecimal(value);
      if (
        fieldName !== 'id' &&
        displayValue !== undefined &&
        displayValue !== null &&
        !isNaN(Number(displayValue))
      ) {
        return <NumberField value={displayValue ?? ''} />;
      } else {
        return <TextField value={displayValue} />;
      }
    };
  } else if (fieldType === 'Url') {
    props.render = (value: any) => {
      return <UrlField value={value} />;
    };
  } else if (fieldType === 'Email') {
    props.render = (value: any) => {
      return <EmailField value={value} />;
    };
  } else if (fieldType === 'Boolean') {
    props.render = (value: any) => {
      return (
        <BooleanField
          value={value}
          trueIcon={<CheckCircleTwoTone twoToneColor="#52c41a" />}
          falseIcon={<CloseCircleTwoTone twoToneColor="red" />}
        />
      );
    };
  } else if (fieldType === 'Radio' || col.kind === 'enum') {
    props.render = (value: any) => {
      return (
        <TagField
          value={t(
            `resources.${resourceName}.enums.${fieldName}.${value}`,
            String(value),
          )}
        />
      );
    };
  } else if (fieldType === 'CheckBox') {
    props.render = (value: any) => {
      return (
        <Space>
          {JSON.parse(value || '[]')?.map?.((v: string, index: number) => (
            <TagField
              key={index}
              value={t(
                `resources.${resourceName}.enums.${fieldName}.${v}`,
                String(v),
              )}
            />
          ))}
        </Space>
      );
    };
  } else if (fieldType === 'Select') {
    if (['multiple', 'tags'].includes((args as any).mode)) {
      props.render = (value: any) => {
        return (
          <Space>
            {JSON.parse(value || '[]')?.map?.((v: string, index: number) => (
              <TagField
                key={index}
                value={t(
                  `resources.${resourceName}.enums.${fieldName}.${v}`,
                  String(v),
                )}
              />
            ))}
          </Space>
        );
      };
    } else {
      props.render = (value: any) => {
        return (
          <TagField
            value={t(
              `resources.${resourceName}.enums.${fieldName}.${value}`,
              String(value),
            )}
          />
        );
      };
    }
  } else if (fieldType === 'Image') {
    props.render = (value: any) => {
      return (
        <Space wrap>
          {JSON.parse(value || '[]')?.map?.((img: any) => (
            <ImageField
              key={img?.response?.name}
              value={img?.thumbUrl}
              title={img?.name}
              width={200}
            />
          ))}
        </Space>
      );
    };
  } else if (fieldType === 'File') {
    props.render = (value: any) => {
      return (
        <Space wrap>
          {JSON.parse((value as any) || '[]')?.map?.((file: any) => (
            <FileField
              key={file?.response?.name}
              src={file?.thumbUrl}
              title={file?.name}
            />
          ))}
        </Space>
      );
    };
  } else if (fieldType === 'JSON') {
    props.render = (value: any) => {
      if (value === null || value === undefined) {
        return <TextField value={value} />;
      }
      const text = typeof value === 'string' ? value : JSON.stringify(value);
      const pretty =
        typeof value === 'string' ? value : JSON.stringify(value, null, 2);
      return (
        <Tooltip
          title={
            <pre
              style={{
                margin: 0,
                maxWidth: 480,
                maxHeight: 360,
                overflow: 'auto',
                whiteSpace: 'pre-wrap',
                wordBreak: 'break-word',
              }}
            >
              {pretty}
            </pre>
          }
        >
          <Typography.Text
            code
            style={{ maxWidth: 320, display: 'inline-block' }}
            ellipsis
          >
            {text}
          </Typography.Text>
        </Tooltip>
      );
    };
  }

  if (tableConfig.header.sorter.includes(fieldName)) {
    props.defaultSortOrder = getDefaultSortOrder(fieldName, sorter);
    props.sorter = true;
  }

  if (tableConfig.header.filter.includes(fieldName)) {
    const field = (model as any)[fieldName];
    const { type: fieldType, args } = col.uiType.formItem;

    if (
      field.kind === 'enum' ||
      ['Radio', 'Select', 'CheckBox'].includes(fieldType)
    ) {
      let options = {};
      if (field.kind === 'enum') {
        options = (modelsEnum as any)[field.type];
      } else {
        options = (args as any).options.reduce(
          (acc: Record<string, string>, cur: string) => {
            acc[cur] = cur;
            return acc;
          },
          {},
        );
      }
      props.filterDropdown = (p: FilterDropdownProps) => {
        const { setSelectedKeys, confirm } = p;
        return (
          <FilterDropdown
            {...p}
            clearFilters={() => {
              setSelectedKeys([]);
              confirm?.();
            }}
          >
            <Select
              style={{ minWidth: 200 }}
              mode="multiple"
              placeholder={t(
                `resources.${resourceName}.filters.${fieldName}`,
                'Select value',
              )}
              options={Object.entries(options).map(([k, v]) => ({
                value: v,
                label: t(
                  `resources.${resourceName}.enums.${fieldName}.${k}`,
                  String(k),
                ),
              }))}
            />
          </FilterDropdown>
        );
      };
      props.defaultFilteredValue = getDefaultFilter(fieldName, filters, 'in');
    } else if (field.kind === 'object') {
      props.filterDropdown = (p: FilterDropdownProps) => {
        const { setSelectedKeys, confirm } = p;
        return (
          <FilterDropdown
            {...p}
            clearFilters={() => {
              setSelectedKeys([]);
              confirm?.();
            }}
            mapValue={(selectedKeys) =>
              selectedKeys.map((i) => parseInt(i.toString()))
            }
          >
            <Select
              style={{ minWidth: 200 }}
              mode="multiple"
              placeholder={t(
                `resources.${field.type.toLowerCase()}.name`,
                String(field.type),
              )}
              {...relationSelectProps[field.name]}
            />
          </FilterDropdown>
        );
      };
      props.defaultFilteredValue = getDefaultFilter(
        `${field.name}.id`,
        filters,
        'in',
      );
    }
  }

  const agentHeaderAttrs = agentAttrs({
    type: 'list-column',
    field: fieldName,
    resource: resourceName,
    meta: {
      fieldType: col.uiType.formItem.type,
      sortable: tableConfig.header.sorter.includes(fieldName),
      filterable: tableConfig.header.filter.includes(fieldName),
    },
  });

  const { key: colKey, ...restProps } = props;

  return (
    <Table.Column
      key={colKey}
      {...restProps}
      {...col}
      onHeaderCell={() => agentHeaderAttrs}
    />
  );
}

interface SearchFormOptions {
  /** 日期字段名，设为 null 则不使用日期筛选，默认 'createdAt' */
  dateField?: string | null;
}

/**
 * 从 parsedFilters 生成搜索表单的 initialValues
 */
export function getSearchFormInitialValues(
  parsedFilters: any[],
  options: SearchFormOptions = {},
) {
  const { dateField = 'createdAt' } = options;

  const initialValues: Record<string, any> = {
    q: parsedFilters.find((f: any) => f.field === 'q')?.value,
  };

  // 仅当 dateField 存在时才处理日期筛选
  if (dateField) {
    const hasDateFilter = parsedFilters.find(
      (f: any) => f.field === dateField && f.operator === 'gte',
    );

    initialValues[dateField] = hasDateFilter
      ? [
          dayjs(
            parsedFilters.find(
              (f: any) => f.field === dateField && f.operator === 'gte',
            )?.value,
          ),
          dayjs(
            parsedFilters.find(
              (f: any) => f.field === dateField && f.operator === 'lte',
            )?.value,
          ),
        ]
      : [undefined, undefined];
  }

  return initialValues;
}

/**
 * 创建搜索表单的 onFinish 处理函数
 */
export function createSearchFormOnFinish(
  setCurrent: (page: number) => void,
  setFilters: (fn: (prev: CrudFilters) => CrudFilters) => void,
  options: SearchFormOptions = {},
) {
  const { dateField = 'createdAt' } = options;
  const filterFields = dateField ? ['q', dateField] : ['q'];

  return (values: any) => {
    const fs: CrudFilters = [];
    const trimedQ = (values.q || '').trim();

    // 处理日期筛选
    if (dateField) {
      const dateValue = values[dateField];
      if (dateValue && dateValue[0]) {
        fs.push(
          {
            field: dateField,
            operator: 'gte',
            value: dateValue[0]?.toISOString?.(),
          },
          {
            field: dateField,
            operator: 'lte',
            value: dateValue[1]?.toISOString?.(),
          },
        );
      }
    }

    // 处理关键词筛选
    if (trimedQ) {
      fs.push({ field: 'q', operator: 'eq', value: trimedQ });
    }

    setCurrent(1);
    setFilters((prevFilters) =>
      unionFilters(
        [],
        fs,
        prevFilters.filter((item: any) => !filterFields.includes(item.field)),
      ),
    );
  };
}
