import { useCallback, useEffect, useMemo, useState } from "react";
import {
  Button,
  Card,
  Empty,
  message,
  Modal,
  Select,
  Space,
  Table,
  Tag,
  Typography,
} from "antd";
import type { ColumnsType } from "antd/es/table";
import {
  assignUserRolesUsingPut,
  listAuthPermissionsUsingGet,
  listAuthRolesUsingGet,
  listAuthUsersUsingGet,
} from "./settings.apis";
import type {
  AuthPermissionInfo,
  AuthRoleInfo,
  AuthUserWithRoles,
} from "./settings.apis";

interface ApiResponse<T> {
  code: string;
  message: string;
  data: T;
}

interface UserPermissionManagementProps {
  canManageUsers: boolean;
  canViewRoles: boolean;
  canViewPermissions: boolean;
}

export default function UserPermissionManagement({
  canManageUsers,
  canViewRoles,
  canViewPermissions,
}: UserPermissionManagementProps) {
  const [loading, setLoading] = useState(false);
  const [users, setUsers] = useState<AuthUserWithRoles[]>([]);
  const [roles, setRoles] = useState<AuthRoleInfo[]>([]);
  const [permissions, setPermissions] = useState<AuthPermissionInfo[]>([]);
  const [editingUser, setEditingUser] = useState<AuthUserWithRoles | null>(null);
  const [selectedRoleCodes, setSelectedRoleCodes] = useState<string[]>([]);
  const [submitting, setSubmitting] = useState(false);

  const canShowAnything = canManageUsers || canViewRoles || canViewPermissions;
  const canAssignRoles = canManageUsers && roles.length > 0;

  const roleNameMap = useMemo(
    () => new Map(roles.map((role) => [role.roleCode, role.roleName || role.roleCode])),
    [roles]
  );
  const roleCodeToIdMap = useMemo(
    () => new Map(roles.map((role) => [role.roleCode, role.id])),
    [roles]
  );

  const loadData = useCallback(async () => {
    setLoading(true);
    try {
      const requestTasks: Array<Promise<unknown>> = [];
      if (canManageUsers || canViewRoles || canViewPermissions) {
        requestTasks.push(listAuthUsersUsingGet());
      }
      if (canManageUsers || canViewRoles) {
        requestTasks.push(listAuthRolesUsingGet());
      }
      if (canViewPermissions) {
        requestTasks.push(listAuthPermissionsUsingGet());
      }
      const responses = await Promise.all(requestTasks);
      let index = 0;
      if (canManageUsers || canViewRoles || canViewPermissions) {
        const userResponse = responses[index++] as ApiResponse<AuthUserWithRoles[]>;
        setUsers(userResponse?.data ?? []);
      }
      if (canManageUsers || canViewRoles) {
        const roleResponse = responses[index++] as ApiResponse<AuthRoleInfo[]>;
        setRoles(roleResponse?.data ?? []);
      } else {
        setRoles([]);
      }
      if (canViewPermissions) {
        const permissionResponse = responses[index++] as ApiResponse<AuthPermissionInfo[]>;
        setPermissions(permissionResponse?.data ?? []);
      } else {
        setPermissions([]);
      }
    } catch (error) {
      message.error("加载用户权限信息失败");
      console.error("加载用户权限信息失败:", error);
    } finally {
      setLoading(false);
    }
  }, [canManageUsers, canViewPermissions, canViewRoles]);

  useEffect(() => {
    if (!canShowAnything) {
      return;
    }
    void loadData();
  }, [canShowAnything, loadData]);

  const userColumns: ColumnsType<AuthUserWithRoles> = [
    {
      title: "用户名",
      dataIndex: "username",
      key: "username",
      width: 180,
    },
    {
      title: "姓名",
      dataIndex: "fullName",
      key: "fullName",
      width: 180,
      render: (value?: string) => value || "-",
    },
    {
      title: "邮箱",
      dataIndex: "email",
      key: "email",
      render: (value?: string) => value || "-",
    },
    {
      title: "状态",
      dataIndex: "enabled",
      key: "enabled",
      width: 120,
      render: (enabled?: boolean) =>
        enabled ? <Tag color="green">启用</Tag> : <Tag color="default">禁用</Tag>,
    },
    {
      title: "角色",
      dataIndex: "roleCodes",
      key: "roleCodes",
      render: (roleCodes: string[]) => (
        <Space wrap>
          {(roleCodes ?? []).map((roleCode) => (
            <Tag key={roleCode}>{roleNameMap.get(roleCode) || roleCode}</Tag>
          ))}
        </Space>
      ),
    },
    {
      title: "操作",
      key: "actions",
      width: 120,
      render: (_, record) => (
        <Button
          type="link"
          disabled={!canAssignRoles}
          onClick={() => {
            setEditingUser(record);
            setSelectedRoleCodes(record.roleCodes ?? []);
          }}
        >
          分配角色
        </Button>
      ),
    },
  ];

  const roleColumns: ColumnsType<AuthRoleInfo> = [
    { title: "角色编码", dataIndex: "roleCode", key: "roleCode", width: 220 },
    { title: "角色名称", dataIndex: "roleName", key: "roleName", width: 180 },
    {
      title: "状态",
      dataIndex: "enabled",
      key: "enabled",
      width: 120,
      render: (enabled?: boolean) =>
        enabled ? <Tag color="green">启用</Tag> : <Tag color="default">禁用</Tag>,
    },
    {
      title: "描述",
      dataIndex: "description",
      key: "description",
      render: (value?: string) => value || "-",
    },
  ];

  const permissionColumns: ColumnsType<AuthPermissionInfo> = [
    {
      title: "权限编码",
      dataIndex: "permissionCode",
      key: "permissionCode",
      width: 260,
    },
    {
      title: "权限名称",
      dataIndex: "permissionName",
      key: "permissionName",
      width: 200,
    },
    {
      title: "模块",
      dataIndex: "module",
      key: "module",
      width: 140,
      render: (value?: string) => value || "-",
    },
    {
      title: "动作",
      dataIndex: "action",
      key: "action",
      width: 120,
      render: (value?: string) => value || "-",
    },
    {
      title: "接口",
      key: "api",
      render: (_, record) =>
        record.pathPattern ? `${record.method || "ALL"} ${record.pathPattern}` : "-",
    },
  ];

  const handleAssignRoles = async () => {
    if (!editingUser) {
      return;
    }
    if (selectedRoleCodes.length === 0) {
      message.warning("请至少选择一个角色");
      return;
    }
    const roleIds = selectedRoleCodes
      .map((roleCode) => roleCodeToIdMap.get(roleCode))
      .filter((roleId): roleId is string => Boolean(roleId));
    if (roleIds.length !== selectedRoleCodes.length) {
      message.error("角色映射失败，请刷新后重试");
      return;
    }
    setSubmitting(true);
    try {
      await assignUserRolesUsingPut(editingUser.id, roleIds);
      message.success("角色分配成功");
      setEditingUser(null);
      setSelectedRoleCodes([]);
      await loadData();
    } catch (error) {
      message.error("角色分配失败");
      console.error("角色分配失败:", error);
    } finally {
      setSubmitting(false);
    }
  };

  if (!canShowAnything) {
    return <Empty description="当前账号无用户与权限管理权限" />;
  }

  return (
    <Space direction="vertical" size={16} className="w-full">
      <Card title="用户管理">
        <Table
          loading={loading}
          rowKey="id"
          dataSource={users}
          columns={userColumns}
          pagination={{ pageSize: 10, showSizeChanger: false }}
        />
      </Card>
      {canViewRoles && (
        <Card title="角色列表">
          <Table
            loading={loading}
            rowKey="id"
            dataSource={roles}
            columns={roleColumns}
            pagination={{ pageSize: 8, showSizeChanger: false }}
          />
        </Card>
      )}
      {canViewPermissions && (
        <Card title="权限列表">
          <Table
            loading={loading}
            rowKey="id"
            dataSource={permissions}
            columns={permissionColumns}
            pagination={{ pageSize: 10, showSizeChanger: false }}
          />
        </Card>
      )}
      <Modal
        title={`分配角色 - ${editingUser?.username || ""}`}
        open={Boolean(editingUser)}
        confirmLoading={submitting}
        onOk={() => {
          void handleAssignRoles();
        }}
        onCancel={() => {
          setEditingUser(null);
          setSelectedRoleCodes([]);
        }}
      >
        {roles.length === 0 ? (
          <Typography.Text type="secondary">暂无可分配角色</Typography.Text>
        ) : (
          <Select
            mode="multiple"
            className="w-full"
            placeholder="请选择角色"
            value={selectedRoleCodes}
            onChange={(values) => setSelectedRoleCodes(values)}
            options={roles.map((role) => ({
              value: role.roleCode,
              label: `${role.roleName} (${role.roleCode})`,
            }))}
          />
        )}
      </Modal>
    </Space>
  );
}

