import {Avatar, Button, Form, Input, message, Modal, Tag, Tooltip, Typography} from 'antd';
import React, {useEffect, useMemo, useState} from 'react';
import XinTable from '@/components/XinTable';
import type {XinTableColumn, XinTableProps} from "@/components/XinTable/typings.ts";
import type ISysUser from "@/domain/iSysUser.ts";
import AuthButton from "@/components/AuthButton";
import type {DeptFieldType, ResetPasswordType, RoleFieldType} from "@/api/system/sys_user";
import {deptField, resetPassword, roleField} from "@/api/system/sys_user";
import {RedoOutlined} from "@ant-design/icons";
import {useTranslation} from "react-i18next";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import useAuth from "@/hooks/useAuth.ts";
const { Title, Text } = Typography;
dayjs.extend(relativeTime);

const Table: React.FC = () => {
  const {t} = useTranslation();
  const { auth } = useAuth();
  /** 角色选项数据 */
  const [roles, setRoles] = useState<RoleFieldType[]>([]);
  /** 部门选项数据 */
  const [departments, setDepartments] = useState<DeptFieldType[]>([]);
  /** 部门选项数据映射 */
  const departmentMap: Map<number, string> = useMemo(() => {
    const map: Map<number, string> = new Map();
    const buildMap = (dept: DeptFieldType[]) => {
      dept.forEach(item => {
        map.set(item.dept_id, item.name);
        if (item.children && item.children.length > 0) {
          buildMap(item.children);
        }
      })
    }
    buildMap(departments);
    return map;
  }, [departments]);

  /** 高级表格列配置 */
  const columns: XinTableColumn<ISysUser>[] = [
    {
      title: t("system.user.id"),
      dataIndex: 'id',
      hideInForm: true,
      sorter: true,
      align: 'center',
    },
    {
      title: t("system.user.username"),
      dataIndex: 'username',
      valueType: 'text',
      align: 'center',
      required: true,
      rules: [{required: true, message: t("system.user.username.required")}],
    },
    {
      title: t("system.user.nickname"),
      dataIndex: 'nickname',
      valueType: 'text',
      align: 'center',
      required: true,
      rules: [{required: true, message: t("system.user.nickname.required")}],
    },
    {
      title: t("system.user.sex"),
      dataIndex: 'sex',
      valueType: 'radio',
      filters: [
        { text: t("system.user.sex.0"), value: 0 },
        { text: t("system.user.sex.1"), value: 1 },
      ],
      align: 'center',
      hideInSearch: true,
      fieldProps: {
        options: [
          { value: 0, label: t("system.user.sex.0") },
          { value: 1, label: t("system.user.sex.1") },
        ]
      },
      render: (value: number) => {
        return value === 0 ? t("system.user.sex.0") : t("system.user.sex.1");
      }
    },
    {
      title: t("system.user.email"),
      dataIndex: 'email',
      valueType: 'text',
      align: 'center',
      required: true,
      rules: [{required: true, message: t("system.user.email.required")}],
    },
    {
      title: t("system.user.role"),
      dataIndex: 'role_id',
      valueType: 'select',
      align: 'center',
      hideInSearch: true,
      required: true,
      rules: [{required: true, message: t("system.user.role.required")}],
      render: (value: number[]) => (
        <>
          {value.map(item => (
            <Tag color={'magenta'}>
              {roles.find(r => r.role_id === item)?.name || '-'}
            </Tag>
          ))}
        </>
      ),
      fieldProps: {
        mode: 'multiple',
        options: roles.map(r => ({ label: r.name, value: r.role_id })),
      },
    },
    {
      title: t("system.user.dept"),
      dataIndex: 'dept_id',
      valueType: 'treeSelect',
      align: 'center',
      required: true,
      rules: [{required: true, message: t("system.user.dept.required")}],
      render: (value) => (
        // 嵌套寻找部门名称
        <Tag color={'volcano'}>{departmentMap.get(value) || '-'}</Tag>
      ),
      fieldProps: {
        treeData: departments,
        fieldNames: {label: 'name', value: 'dept_id'}
      }
    },
    {
      title: t("system.user.status"),
      dataIndex: 'status',
      valueType: 'radioButton',
      fieldProps: {
        options: [
          { value: 0, label: t("system.user.status.0") },
          { value: 1, label: t("system.user.status.1") },
        ]
      },
      render: (value: number) => {
        return value === 1
          ? <Tag color="success">{t("system.user.status.1")}</Tag>
          : <Tag color="error">{t("system.user.status.0")}</Tag>;
      },
      required: true,
      rules: [{required: true, message: t("system.user.status.required")}],
      filters: [
        { text: t("system.user.status.0"), value: 0 },
        { text: t("system.user.status.1"), value: 1 },
      ],
      hideInSearch: true,
      align: 'center',
    },
    {
      title: t("system.user.mobile"),
      dataIndex: 'mobile',
      valueType: 'text',
      required: true,
      rules: [{required: true, message: t("system.user.mobile.required")}],
      align: 'center',
    },
    {
      title: t("system.user.avatar"),
      dataIndex: 'avatar_url',
      hideInSearch: true,
      hideInForm: true,
      render: (_, entity: ISysUser) => <Avatar size={'small'} src={entity.avatar_url}></Avatar>,
      align: 'center',
    },
    {
      title: t("system.user.password"),
      dataIndex: 'password',
      valueType: 'password',
      hideInTable: true,
      hideInSearch: true,
      hideInUpdate: true,
      rules: [{required: true, message: t("system.user.password.required")}],
      fieldProps: {autoComplete: 'new-password'},
    },
    {
      title: t("system.user.rePassword"),
      dataIndex: 'rePassword',
      valueType: 'password',
      hideInTable: true,
      hideInSearch: true,
      hideInUpdate: true,
      rules: [{required: true, message: t("system.user.rePassword.required")}],
      fieldProps: {autoComplete: 'new-password'},
    },
    {
      title: t("system.user.created_at"),
      hideInForm: true,
      hideInSearch: true,
      dataIndex: 'created_at',
      align: 'center',
      render: (value: string) => value ? dayjs(value).fromNow() : '-',
    },
    {
      title: t("system.user.updated_at"),
      hideInForm: true,
      hideInSearch: true,
      dataIndex: 'updated_at',
      align: 'center',
      render: (value: string) => value ? dayjs(value).fromNow() : '-',
    },
  ];

  /** 修改密码相关状态 */
  const [isModalOpen, setIsModalOpen] = useState(false);
  const [resetUserId, setResetUserId] = useState<number>();
  const [buttonLoading, setButtonLoading] = useState<boolean>(false);

  /** 打开重置密码框 */
  const showRedoModal = (id: number) => {
    setIsModalOpen(true);
    setResetUserId(id);
  };

  /** 提交重置密码 */
  const handleRedoSubmit = async (values: ResetPasswordType) => {
    try {
      setButtonLoading(true);
      await resetPassword({...values, id: resetUserId!});
      setIsModalOpen(false);
      message.success(t("system.user.resetSuccess"));
    } finally {
      setButtonLoading(false);
    }
  };

  useEffect(() => {
    if(auth('system.user.dept')) {
      deptField().then(res => setDepartments(res.data.data!));
    }
    if(auth('system.user.role')) {
      roleField().then(res => setRoles(res.data.data!));
    }
  }, []);

  /** 操作栏之后渲染 */
  const operateRender: XinTableProps['operateRender'] = (record, dom) => ([
    <>
      {record.id !== 1 &&
        <AuthButton auth={'system.user.resetPassword'}>
          <Tooltip title={t("system.user.resetPassword")}>
            <Button
              variant={'solid'}
              color={'pink'}
              icon={<RedoOutlined/>}
              size={'small'}
              onClick={() => showRedoModal(record.id!)}
            />
          </Tooltip>
        </AuthButton>
      }
    </>,
    dom.del,
    dom.edit
  ]);

  /** 表格配置 */
  const tableProps: XinTableProps<ISysUser> = {
    api: '/system/user',
    columns,
    rowKey: 'id',
    accessName: 'system.user',
    operateRender,
    scroll: { x: 1400 },
    editShow: (i) => i.id !== 1,
    deleteShow: (i) => i.id !== 1,
    formProps: {
      grid: true,
      colProps: {span: 12},
      rowProps: {gutter: [30, 0]},
      layout: 'vertical'
    },
    modalProps: {
      width: 800,
    },
    cardProps: {
      variant: 'borderless'
    },
    pagination: {
      size: 'small',
        style: {
        marginBottom: 0
      }
    }
  }

  return (
    <>
      <div className={'mb-5'}>
        <Title level={3}>{t("system.user.page.title")}</Title>
        <Text type="secondary">{t("system.user.page.description")}</Text>
      </div>
      <XinTable<ISysUser> {...tableProps} />
      <Modal
        title={t("system.user.resetPassword")}
        closable={{'aria-label': 'Custom Close Button'}}
        open={isModalOpen}
        footer={null}
        styles={{body: {paddingTop: 20}}}
        onCancel={() => setIsModalOpen(false)}
      >
        <Form<ResetPasswordType> autoComplete="off" layout={'vertical'} onFinish={handleRedoSubmit}>
          <Form.Item
            label={t("system.user.password")}
            name="password"
            rules={[{required: true, message: t("system.user.password.required")}]}
          >
            <Input.Password/>
          </Form.Item>
          <Form.Item
            label={t("system.user.rePassword")}
            name="rePassword"
            rules={[{required: true, message: t("system.user.rePassword.required")}]}
          >
            <Input.Password/>
          </Form.Item>
          <Form.Item label={null} style={{marginTop: 30}}>
            <Button type="primary" block size={'large'} htmlType="submit" loading={buttonLoading}>
              {t("system.user.resetButton")}
            </Button>
          </Form.Item>
        </Form>
      </Modal>
    </>
  );
};

export default Table;
