import React, { useEffect } from 'react';
import type { RolePageTreeNode } from '../types';
import { useModalForm } from '@refinedev/antd';
import { type HttpError, type RedirectAction, useList } from '@refinedev/core';
import { Form, Input, Modal, Space, Tag, TreeSelect, Typography } from 'antd';
import { Role } from '@/types/role';
import { RoleSelect } from '../queries';

type RoleFormFields = Partial<Role> & {
  pageIds?: Array<number | string>;
};

type Props = {
  action: 'create' | 'edit';
  id?: number;
  redirect?: RedirectAction;
  onMutationSuccess?: () => void;
  onCancel?: () => void;
  pageTreeData?: RolePageTreeNode[];
  selectedPageIds?: Array<number | string>;
  selectedActions?: string[];
};

const accessActionList = ['read', 'create', 'update', 'delete'];
const SPECIAL_CHAR_PATTERN = /[^\u4e00-\u9fa5a-zA-Z0-9\s-_]/;

const buildPageNodeMap = (
  nodes?: RolePageTreeNode[],
): Map<string, RolePageTreeNode> => {
  const nodeMap = new Map<string, RolePageTreeNode>();

  const traverse = (items?: RolePageTreeNode[]) => {
    items?.forEach((item) => {
      nodeMap.set(String(item.value), item);
      if (item.children?.length) {
        traverse(item.children);
      }
    });
  };

  traverse(nodes);
  return nodeMap;
};

const collectDescendantIds = (
  selectedIds?: Array<string | number>,
  nodes?: RolePageTreeNode[],
): number[] => {
  if (!selectedIds?.length || !nodes?.length) {
    return [];
  }

  const nodeMap = buildPageNodeMap(nodes);
  const collected = new Set<string>();

  const includeNodeAndChildren = (node: RolePageTreeNode) => {
    collected.add(String(node.value));
    node.children?.forEach(includeNodeAndChildren);
  };

  selectedIds.forEach((rawId) => {
    const node = nodeMap.get(String(rawId));
    if (!node) {
      return;
    }
    includeNodeAndChildren(node);
  });

  return Array.from(collected).map((id) => Number(id));
};

export const RoleFormModal: React.FC<Props> = ({
  action,
  id,
  redirect,
  onCancel,
  onMutationSuccess,
  pageTreeData,
  selectedPageIds,
  selectedActions,
}) => {
  const { formProps, modalProps, onFinish, close } = useModalForm<
    Role,
    HttpError,
    RoleFormFields
  >({
    resource: 'role',
    action,
    id,
    defaultVisible: true,
    redirect,
    onMutationSuccess: () => {
      onMutationSuccess?.();
    },
    meta: {
      select: RoleSelect,
    },
  });

  // Fetch all roles for name duplication check
  const { data: rolesData } = useList<Role>({
    resource: 'role',
    pagination: {
      mode: 'off',
    },
  });
  const normalizedSelectedPageIds =
    selectedPageIds?.map((pageId) => String(pageId)) ?? [];

  useEffect(() => {
    if (action === 'edit') {
      formProps.form?.setFieldsValue({ pageIds: normalizedSelectedPageIds });
    } else {
      formProps.form?.setFieldsValue({ pageIds: [] });
    }
  }, [action, normalizedSelectedPageIds, formProps.form]);

  // fix react-query cache data type error
  if (
    formProps.initialValues?.resources &&
    typeof formProps.initialValues.resources === 'string'
  ) {
    formProps.initialValues.resources =
      formProps.initialValues.resources.split(',');
  }
  if (
    formProps.initialValues?.actions &&
    typeof formProps.initialValues.actions === 'string'
  ) {
    formProps.initialValues.actions =
      formProps.initialValues.actions.split(',');
  }

  formProps.onFinish = (values) => {
    const formattedValues = {
      ...values,
      pageIds: collectDescendantIds(values.pageIds, pageTreeData),
      resources: Array.isArray(values.resources)
        ? values.resources.join(',')
        : values.resources,
      actions: Array.isArray(values.actions)
        ? values.actions.join(',')
        : values.actions,
    };
    onFinish(formattedValues);
  };

  return (
    <Modal
      {...modalProps}
      width={560}
      onCancel={() => {
        if (onCancel) {
          onCancel();
          return;
        }
        close();
      }}
      title={action === 'create' ? 'Create Role' : 'Edit Role'}
    >
      <Form {...formProps} layout="vertical">
        <Form.Item
          rules={[
            { required: true },
            {
              validator: (_, value) => {
                if (!value || !SPECIAL_CHAR_PATTERN.test(value)) {
                  return Promise.resolve();
                }
                return Promise.reject(
                  new Error('Special characters are not allowed.'),
                );
              },
            },
            {
              validator: async (_, value) => {
                if (!value) {
                  return Promise.resolve();
                }

                const existingRoles = rolesData?.data || [];
                const trimmedValue = value.trim();

                // Check if role name already exists (case-insensitive)
                const isDuplicate = existingRoles.some((role) => {
                  // Skip current role when editing
                  if (action === 'edit' && role.id === id) {
                    return false;
                  }
                  return role.name.toLowerCase() === trimmedValue.toLowerCase();
                });

                if (isDuplicate) {
                  return Promise.reject(
                    new Error(
                      'Role name already exists. Please use a different name.',
                    ),
                  );
                }

                return Promise.resolve();
              },
            },
          ]}
          name="name"
          label="Role name"
        >
          <Input placeholder="Please enter roleName" />
        </Form.Item>

        <Form.Item
          rules={[{ required: true }]}
          name="description"
          label="Role Description"
        >
          <Input placeholder="Please enter description" />
        </Form.Item>

        <Form.Item
          name="pageIds"
          label="Page Permissions"
          initialValue={action === 'edit' ? normalizedSelectedPageIds : []}
        >
          {pageTreeData?.length ? (
            <TreeSelect
              style={{ width: '100%' }}
              treeCheckable
              treeData={pageTreeData}
              treeDefaultExpandAll
              showCheckedStrategy={TreeSelect.SHOW_CHILD}
              maxTagCount={5}
              maxTagPlaceholder={(omittedValues) =>
                `+${omittedValues.length} more...`
              }
              placeholder={
                action === 'edit'
                  ? '编辑角色可以访问的页面'
                  : '请选择角色的可访问页面'
              }
            />
          ) : (
            <>
              <Typography.Text type="secondary">
                No pages are currently linked to this role.
              </Typography.Text>
              <Input type="hidden" />
            </>
          )}
        </Form.Item>

        {action === 'edit' && (
          <Form.Item label="Permission Actions Overview">
            {selectedActions?.length ? (
              <Space size={[8, 8]} wrap>
                {selectedActions.map((actionKey) => (
                  <Tag key={actionKey}>{actionKey}</Tag>
                ))}
              </Space>
            ) : (
              <Typography.Text type="secondary">
                No actions have been granted to this role.
              </Typography.Text>
            )}
          </Form.Item>
        )}

        {/* <Form.Item
          rules={[{ required: true }]}
          name="resources"
          label="Role Resources"
        >
          <Select
            mode="multiple"
            placeholder="Please select roles"
            options={availableResourcesResponse?.allResources
              ?.sort()
              .map((resource: string) => ({
                label: resource,
                value: resource,
              }))}
          />
        </Form.Item>
        <Form.Item
          rules={[{ required: true }]}
          name="actions"
          label="Role Actions"
        >
          <Select
            mode="multiple"
            placeholder="Please select roles"
            options={accessActionList.map((actionItem) => ({
              label: actionItem,
              value: actionItem,
            }))}
          />
        </Form.Item> */}
      </Form>
    </Modal>
  );
};
