import { userApi } from "@/api";
import { FormPageFooter, PageContainer } from "@/components";
import { PermItemType } from "@/types";
import { getAuthorizedIds } from "@/utils";
import { DageLoading } from "@dage/pc-components";
import { Form, Input, Tree } from "antd";
import { FC, Key, useEffect, useMemo, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";

const { TextArea } = Input;

const getCheckedIds = (treeData: PermItemType[], checkedIds: number[]) => {
  const fullyCheckedIds: number[] = [];
  const halfCheckedIds: number[] = [];

  const checkNode = (node: PermItemType): boolean => {
    let allChildrenChecked = true;
    let someChildrenChecked = false;

    if (node.children && node.children.length > 0) {
      for (const child of node.children) {
        const isChildChecked = checkNode(child);
        if (!isChildChecked) allChildrenChecked = false;
        if (isChildChecked) someChildrenChecked = true;
      }
    }

    const isNodeExplicitlyChecked = checkedIds.includes(node.id);

    if (
      isNodeExplicitlyChecked &&
      (allChildrenChecked || node.children?.length === 0)
    ) {
      fullyCheckedIds.push(node.id);
      return true;
    }

    if (
      (someChildrenChecked && !isNodeExplicitlyChecked) ||
      (isNodeExplicitlyChecked && !allChildrenChecked)
    ) {
      halfCheckedIds.push(node.id);
      return true;
    }

    return isNodeExplicitlyChecked;
  };

  treeData.forEach((node) => checkNode(node));
  return { fullyCheckedIds, halfCheckedIds };
};

const RoleEditPage: FC = () => {
  const [form] = Form.useForm();
  const params = useParams();
  const navigate = useNavigate();
  const isEdit = useMemo(() => location.href.indexOf("edit") > -1, [location]);
  const [permTree, setPermTree] = useState<PermItemType[]>([]);
  const [checkedKeys, setCheckedKeys] = useState<Key[]>([]);
  const [halfCheckedKeys, setHalfCheckedKeys] = useState<Key[]>([]);
  const [loading, setLoading] = useState(false);

  const getTree = async () => {
    const data = await userApi.getPermTree();
    setPermTree(data);
  };

  const getDetail = async () => {
    try {
      setLoading(true);
      const data = await userApi.getRole(params.id as string);
      form.setFieldsValue({
        roleName: data.role.roleName,
        roleDesc: data.role.roleDesc,
      });

      const idsRes = getCheckedIds(permTree, getAuthorizedIds(data.permission));
      setCheckedKeys(idsRes.fullyCheckedIds);
      setHalfCheckedKeys(idsRes.halfCheckedIds);
    } finally {
      setLoading(false);
    }
  };

  const handleSubmit = async () => {
    if (!(await form.validateFields())) return;

    const val = form.getFieldsValue();
    await userApi.saveRole({
      ...val,
      resources: [...checkedKeys, ...halfCheckedKeys],
      id: params.id,
    });
    navigate(-1);
  };

  useEffect(() => {
    getTree();
  }, []);

  useEffect(() => {
    if (params.id && permTree.length) getDetail();
  }, [permTree]);

  return (
    <PageContainer title={isEdit ? "编辑角色" : "新增角色"}>
      {loading && <DageLoading />}

      <Form labelCol={{ span: 4 }} form={form}>
        <Form.Item
          label="角色名称"
          name="roleName"
          required
          rules={[{ required: true, message: "请输入内容" }]}
        >
          <Input
            className="w450"
            showCount
            maxLength={10}
            placeholder="请输入内容，最多10字；不能重复"
          />
        </Form.Item>
        <Form.Item label="角色说明" name="roleDesc">
          <TextArea
            className="w450"
            showCount
            style={{ height: 200 }}
            maxLength={200}
            placeholder="请输入内容，最多200字；不能重复"
          />
        </Form.Item>
        <Form.Item label="用户权限">
          <div className="w450">
            <Tree
              checkable
              // @ts-ignore
              treeData={permTree}
              checkedKeys={{
                checked: checkedKeys,
                halfChecked: halfCheckedKeys,
              }}
              fieldNames={{ title: "name", key: "id" }}
              onCheck={(keys, halfKeys) => {
                setCheckedKeys(keys as number[]);
                if (halfKeys.halfCheckedKeys) {
                  setHalfCheckedKeys(halfKeys.halfCheckedKeys as number[]);
                }
              }}
            />
          </div>
        </Form.Item>
      </Form>

      <FormPageFooter onSubmit={handleSubmit} onCancel={() => navigate(-1)} />
    </PageContainer>
  );
};

export default RoleEditPage;
