import { Avatar, Badge, Button, Card, Col, Drawer, Empty, Form, Input, List, Pagination, message, Modal, Popconfirm, Select, Space, Table, Tabs, Tag, Tooltip, Tree, Typography, Row } from "antd";
import type { DataNode } from "antd/es/tree";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import {
  ApartmentOutlined,
  CheckCircleFilled,
  DeleteOutlined,
  EditOutlined,
  FilterOutlined,
  KeyOutlined,
  PlusOutlined,
  SafetyCertificateOutlined,
  SaveOutlined,
  SearchOutlined,
  TeamOutlined,
  UserAddOutlined,
  UserOutlined
} from "@ant-design/icons";
import {
  bindUsersToRole,
  createRole,
  deleteRole,
  fetchUsersByRoleId,
  listPermissions,
  listRolePermissions,
  listTenants,
  listUsers,
  pageRoles,
  saveRolePermissions,
  unbindUserFromRole,
  updateRole
} from "@/api";
import { useDict } from "@/hooks/useDict";
import { usePermission } from "@/hooks/usePermission";
import PageHeader from "@/components/shared/PageHeader";
import type { SysPermission, SysRole, SysTenant, SysUser } from "@/types";
import "./index.less";

const { Text, Title } = Typography;

type PermissionNode = SysPermission & { key: number; children?: PermissionNode[] };
const DEFAULT_STATUS = 1;
const DEFAULT_ROLE_PAGE_SIZE = 10;

function normalizeNumber(value: unknown): number | undefined {
  if (typeof value === "number") {
    return Number.isFinite(value) ? value : undefined;
  }
  if (typeof value === "string" && value.trim() !== "") {
    const parsed = Number(value);
    return Number.isFinite(parsed) ? parsed : undefined;
  }
  if (value && typeof value === "object" && "value" in value) {
    return normalizeNumber((value as { value?: unknown }).value);
  }
  return undefined;
}
function buildPermissionTree(list: SysPermission[]): PermissionNode[] {
  const active = (list || []).filter((permission) => permission.status !== 0);
  const map = new Map<number, PermissionNode>();
  const roots: PermissionNode[] = [];

  active.forEach((item) => {
    map.set(item.permId, { ...item, key: item.permId, children: [] });
  });

  map.forEach((node) => {
    if (node.parentId && node.parentId !== 0) {
      const parent = map.get(node.parentId);
      if (parent) {
        parent.children!.push(node);
      }
    } else {
      roots.push(node);
    }
  });

  const sortNodes = (nodes: PermissionNode[]) => {
    nodes.sort((left, right) => (left.sortOrder || 0) - (right.sortOrder || 0));
    nodes.forEach((node) => node.children && sortNodes(node.children));
  };

  sortNodes(roots);
  return roots;
}

function toTreeData(nodes: PermissionNode[], t: (key: string, options?: Record<string, unknown>) => string, buttonShortLabel: string): DataNode[] {
  return nodes.map((node) => ({
    key: node.permId,
    title: (
      <Space>
        <span>{node.name}</span>
        {node.permType === "button" ? <Tag color="cyan" style={{ fontSize: 10 }}>{buttonShortLabel}</Tag> : null}
      </Space>
    ),
    children: node.children?.length ? toTreeData(node.children, t, buttonShortLabel) : undefined
  }));
}

const generateRoleCode = () => `ROLE_${Date.now().toString(36).toUpperCase()}`;

export default function Roles() {
  const { t } = useTranslation();
  const { can } = usePermission();
  const { items: statusDict } = useDict("sys_common_status");
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  const [data, setData] = useState<SysRole[]>([]);
  const [permissions, setPermissions] = useState<SysPermission[]>([]);
  const [selectedRole, setSelectedRole] = useState<SysRole | null>(null);
  const [selectedPermIds, setSelectedPermIds] = useState<number[]>([]);
  const [halfCheckedIds, setHalfCheckedIds] = useState<number[]>([]);
  const [roleUsers, setRoleUsers] = useState<SysUser[]>([]);
  const [loadingUsers, setLoadingUsers] = useState(false);
  const [allUsers, setAllUsers] = useState<SysUser[]>([]);
  const [userModalOpen, setUserModalOpen] = useState(false);
  const [selectedUserKeys, setSelectedUserKeys] = useState<number[]>([]);
  const [userSearchText, setUserSearchText] = useState("");
  const [searchText, setSearchText] = useState("");
  const [rolePage, setRolePage] = useState({ current: 1, size: DEFAULT_ROLE_PAGE_SIZE, total: 0 });

  const handleSearch = () => {
    setSearchText((value) => value.trim());
    setRolePage((prev) => ({ ...prev, current: 1 }));
  };

  const handleResetSearch = () => {
    setSearchText("");
    setFilterTenantId(undefined);
    setRolePage((prev) => ({ ...prev, current: 1 }));
  };
  const [filterTenantId, setFilterTenantId] = useState<number | undefined>(undefined);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [editing, setEditing] = useState<SysRole | null>(null);
  const [tenants, setTenants] = useState<SysTenant[]>([]);
  const [form] = Form.useForm();

  const isPlatformMode = useMemo(() => {
    const profileStr = sessionStorage.getItem("userProfile");
    if (!profileStr) return false;
    const profile = JSON.parse(profileStr);
    return profile.isPlatformAdmin && localStorage.getItem("activeTenantId") === "0";
  }, []);

  const activeTenantId = useMemo(() => normalizeNumber(localStorage.getItem("activeTenantId")) ?? 0, []);
  const buttonShortLabel = useMemo(() => {
    const label = t("buttonShort");
    return !label || label === "buttonShort" ? "BTN" : label;
  }, [t]);
  const permissionTreeData = useMemo(() => toTreeData(buildPermissionTree(permissions), t, buttonShortLabel), [buttonShortLabel, permissions, t]);


  useEffect(() => {
    if (!isPlatformMode) return;
    listTenants({ current: 1, size: 100 }).then((response) => setTenants(response.records || [])).catch(() => {});
  }, [isPlatformMode]);

  const loadPermissions = async () => {
    try {
      const list = await listPermissions();
      setPermissions(list || []);
    } catch {
      setPermissions([]);
    }
  };

  const selectRole = async (role: SysRole) => {
    setSelectedRole(role);
    try {
      const ids = await listRolePermissions(role.roleId);
      const normalized = (ids || []).map((id) => Number(id)).filter((id) => !Number.isNaN(id));
      const leafIds = normalized.filter((id) => !permissions.some((permission) => permission.parentId === id));
      setSelectedPermIds(leafIds);
      setHalfCheckedIds([]);

      setLoadingUsers(true);
      const users = await fetchUsersByRoleId(role.roleId);
      setRoleUsers(users || []);
    } finally {
      setLoadingUsers(false);
    }
  };

  const loadRoles = async (page = rolePage.current, size = rolePage.size) => {
    setLoading(true);
    try {
      const response = await pageRoles({
        current: page,
        size,
        tenantId: isPlatformMode ? filterTenantId : activeTenantId,
        keyword: searchText || undefined
      });
      const roles = response?.records || [];
      setRolePage({ current: page, size, total: response?.total || 0 });
      setData(roles);
      if (roles.length === 0) {
        setSelectedRole(null);
        setRoleUsers([]);
        setSelectedPermIds([]);
        setHalfCheckedIds([]);
      } else if (!selectedRole) {
        await selectRole(roles[0]);
      } else {
        const updated = roles.find((role) => role.roleId === selectedRole.roleId);
        if (updated) {
          setSelectedRole(updated);
        } else {
          await selectRole(roles[0]);
        }
      }
      await loadPermissions();
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    loadRoles(rolePage.current, rolePage.size);
  }, [filterTenantId, rolePage.current, rolePage.size, searchText]);

  const loadAllUsers = async () => {
    try {
      const list = await listUsers();
      setAllUsers(list || []);
    } catch {
      setAllUsers([]);
    }
  };

  const openUserModal = () => {
    loadAllUsers();
    setSelectedUserKeys([]);
    setUserModalOpen(true);
  };

  const handleAddUsers = async () => {
    if (!selectedRole || selectedUserKeys.length === 0) return;
    await bindUsersToRole(selectedRole.roleId, selectedUserKeys);
    message.success(t("common.success"));
    setUserModalOpen(false);
    selectRole(selectedRole);
  };

  const handleUnbindUser = async (userId: number) => {
    if (!selectedRole) return;
    if (selectedRole.roleCode === "TENANT_ADMIN" && roleUsers.length <= 1) {
      message.warning(t("rolesExt.tenantAdminWarning"));
      return;
    }
    await unbindUserFromRole(selectedRole.roleId, userId);
    message.success(t("common.success"));
    selectRole(selectedRole);
  };

  const filteredModalUsers = useMemo(() => {
    const existingIds = new Set(roleUsers.map((user) => user.userId));
    return allUsers.filter(
      (user) =>
        !existingIds.has(user.userId) &&
        (user.username.toLowerCase().includes(userSearchText.toLowerCase()) || user.displayName.toLowerCase().includes(userSearchText.toLowerCase()))
    );
  }, [allUsers, roleUsers, userSearchText]);



  const openCreate = () => {
    setEditing(null);
    form.resetFields();
    form.setFieldsValue({ status: 1, tenantId: isPlatformMode ? undefined : activeTenantId });
    setDrawerOpen(true);
  };

  const openEditBasic = (event: React.MouseEvent, record: SysRole) => {
    event.stopPropagation();
    setEditing(record);
    form.setFieldsValue(record);
    setDrawerOpen(true);
  };

  const handleRemove = async (event: React.MouseEvent, id: number) => {
    event.stopPropagation();
    await deleteRole(id);
    message.success(t("common.success"));
    if (selectedRole?.roleId === id) setSelectedRole(null);
    loadRoles(rolePage.current, rolePage.size);
  };

  const submitBasic = async () => {
    const values = await form.validateFields();
    setSaving(true);
    try {
      const payload: Partial<SysRole> = {
        roleCode: editing?.roleCode || values.roleCode || generateRoleCode(),
        roleName: values.roleName,
        remark: values.remark,
        status: values.status ?? DEFAULT_STATUS,
        tenantId: values.tenantId
      };
      if (editing) {
        await updateRole(editing.roleId, payload);
      } else {
        await createRole(payload);
      }
      message.success(t("common.success"));
      setDrawerOpen(false);
      loadRoles(rolePage.current, rolePage.size);
    } finally {
      setSaving(false);
    }
  };

  const handleRolePageChange = (page: number, pageSize: number) => {
    setRolePage((prev) => ({ ...prev, current: page, size: pageSize }));
  };

  const savePermissions = async () => {
    if (!selectedRole) return;
    setSaving(true);
    try {
      await saveRolePermissions(selectedRole.roleId, Array.from(new Set([...selectedPermIds, ...halfCheckedIds])));
      message.success(t("common.success"));
    } finally {
      setSaving(false);
    }
  };

  return (
    <div className="app-page roles-page-v2">
      <PageHeader
        title={t("roles.title")}
        subtitle={t("roles.subtitle")}
      />

      <div className="app-page__page-actions">
        {can("sys:role:create") && <Button type="primary" icon={<PlusOutlined />} onClick={openCreate}>{t("common.create")}</Button>}
      </div>

      <div className="roles-layout">
        <Row gutter={24} className="roles-layout__row">
          <Col span={7} className="roles-layout__side">
            <Card title={<Space><ApartmentOutlined /><span>{t("rolesExt.roleList")}</span>
              {/*<Badge count={rolePage.total} overflowCount={999} className="roles-count-badge" />*/}
            </Space>} bordered={false} className="app-page__panel-card roles-side-card">
              <div className="role-search-panel">
                {isPlatformMode && (
                  <Select
                    placeholder={t("rolesExt.filterTenant")}
                    style={{ width: "100%" }}
                    allowClear
                    suffixIcon={<FilterOutlined />}
                    value={filterTenantId}
                    onChange={(value) => { setFilterTenantId(normalizeNumber(value)); setRolePage((prev) => ({ ...prev, current: 1 })); }}
                    options={tenants.map((tenant) => ({ label: tenant.tenantName, value: tenant.id }))}
                  />
                )}
                <div className="role-search-bar">
                  <Input placeholder={t("roles.searchPlaceholder")} prefix={<SearchOutlined style={{ color: "#94a3b8" }} />} value={searchText} onChange={(event) => setSearchText(event.target.value)} allowClear />
                  <Button type="default" onClick={handleResetSearch}>{t("common.reset")}</Button>
                </div>
              </div>

              <div className="role-list-container-v3">
                <List
                  loading={loading}
                  dataSource={data}
                  pagination={false}
                  locale={{ emptyText: <Empty description={t("rolesExt.noRolesFound")} image={Empty.PRESENTED_IMAGE_SIMPLE} /> }}
                  renderItem={(item) => (
                    <div key={item.roleId} className={`role-item-card-v3 ${selectedRole?.roleId === item.roleId ? "active" : ""}`} onClick={() => selectRole(item)}>
                      <div className="role-item-symbol" aria-hidden="true">
                        <SafetyCertificateOutlined />
                      </div>
                      <div className="role-item-main">
                        <div className="role-item-name-row">
                          <Text strong className="role-name">{item.roleName}</Text>
                          {isPlatformMode && <Tag color="blue" style={{ fontSize: 10, scale: "0.8", margin: "0 0 0 4px", borderRadius: "10px" }}>{item.tenantId === 0 ? t("rolesExt.systemTenant") : tenants.find((tenant) => tenant.id === item.tenantId)?.tenantName || `${t("rolesExt.tenantLabel")}:${item.tenantId}`}</Tag>}
                          {item.status === 0 && <Tag color="error" style={{ fontSize: 10, scale: "0.8", margin: 0 }}>{t("rolesExt.disabled")}</Tag>}
                        </div>
                        <Text type="secondary" className="role-code">{item.roleCode}</Text>
                      </div>
                      {selectedRole?.roleId === item.roleId ? (
                        <div className="role-item-selected-mark" aria-hidden="true">
                          <CheckCircleFilled />
                        </div>
                      ) : null}
                      <div className="role-item-actions">
                        <Space size={4}>
                          <Tooltip title={t("common.edit")}>
                            <Button type="text" size="small" icon={<EditOutlined />} onClick={(event) => openEditBasic(event, item)} />
                          </Tooltip>
                          {item.roleCode !== "ADMIN" && (
                            <Popconfirm title={t("rolesExt.deleteRole")} okText={t("common.confirm")} cancelText={t("common.cancel")} onConfirm={(event) => handleRemove(event!, item.roleId)}>
                              <Button type="text" size="small" danger icon={<DeleteOutlined />} onClick={(event) => event.stopPropagation()} />
                            </Popconfirm>
                          )}
                        </Space>
                      </div>
                    </div>
                  )}
                />
              </div>
              <div className="role-list-pagination">
                <Pagination
                  current={rolePage.current}
                  pageSize={rolePage.size}
                  total={rolePage.total}
                  size="small"
                  onChange={handleRolePageChange}
                  showSizeChanger
                  pageSizeOptions={["10", "20", "50"]}
                />
              </div>
            </Card>
          </Col>

          <Col span={17} className="roles-layout__detail">
            {selectedRole ? (
              <Card
                className="app-page__panel-card roles-detail-card"
                bordered={false}
                title={<div className="role-detail-header"><div className="role-detail-icon"><SafetyCertificateOutlined /></div><div className="role-detail-heading"><div className="role-detail-title">{selectedRole.roleName}</div><Text type="secondary" className="role-detail-code">{selectedRole.roleCode}</Text></div></div>}
                extra={<Button type="primary" icon={<SaveOutlined />} loading={saving} onClick={savePermissions} disabled={!can("sys:role:permission:save") || (selectedRole.roleCode === "TENANT_ADMIN" && !isPlatformMode)} style={{ borderRadius: "6px" }}>{t("common.save")}</Button>}
              >
                <Tabs defaultActiveKey="permissions" className="role-detail-tabs">
                  <Tabs.TabPane tab={<Space><KeyOutlined />{t("roles.funcPerms")}</Space>} key="permissions">
                    <div className="role-detail-pane">
                      <div className="permission-tree-wrapper">
                        <Tree
                          checkable
                          selectable={false}
                          checkStrictly={false}
                          treeData={permissionTreeData}
                          checkedKeys={selectedPermIds}
                          onCheck={(keys, info) => {
                            const checked = Array.isArray(keys) ? keys : keys.checked;
                            const halfChecked = info.halfCheckedKeys || [];
                            setSelectedPermIds(checked.map((key) => Number(key)));
                            setHalfCheckedIds(halfChecked.map((key) => Number(key)));
                          }}
                          defaultExpandAll
                        />
                      </div>
                    </div>
                  </Tabs.TabPane>
                  <Tabs.TabPane tab={<Space><TeamOutlined />{t("rolesExt.membersTab")} ({roleUsers.length})</Space>} key="users">
                    <div className="role-detail-pane">
                      <div className="role-members-toolbar">
                        <Title level={5} style={{ margin: 0 }}>{t("rolesExt.assignedUsers")}</Title>
                        <Button type="primary" ghost icon={<UserAddOutlined />} onClick={openUserModal} disabled={!can("sys:role:update")}>{t("rolesExt.bindUser")}</Button>
                      </div>
                      <Table
                        rowKey="userId"
                        size="small"
                        loading={loadingUsers}
                        dataSource={roleUsers}
                        pagination={{ pageSize: 10, size: "small" }}
                        columns={[
                          {
                            title: t("users.userInfo"),
                            render: (_: any, user: SysUser) => (
                              <Space>
                                <Avatar size="small" icon={<UserOutlined />} style={{ backgroundColor: "#f0f2f5", color: "#8c8c8c" }} />
                                <div>
                                  <div style={{ fontWeight: 500 }}>{user.displayName}</div>
                                  <div style={{ fontSize: 11, color: "#bfbfbf" }}>@{user.username}</div>
                                </div>
                              </Space>
                            )
                          },
                          { title: t("rolesExt.phone"), dataIndex: "phone", className: "tabular-nums" },
                          { title: t("common.status"), dataIndex: "status", width: 80, render: (status: number) => <Tag color={status === 1 ? "green" : "red"}>{status === 1 ? t("logsExt.success") : t("rolesExt.disabled")}</Tag> },
                          {
                            title: t("common.action"),
                            key: "action",
                            width: 80,
                            render: (_: any, user: SysUser) => (
                              <Popconfirm title={t("rolesExt.removeBinding")} okText={t("common.confirm")} cancelText={t("common.cancel")} onConfirm={() => handleUnbindUser(user.userId)} disabled={!can("sys:role:update")}>
                                <Button type="text" danger size="small" icon={<DeleteOutlined />} disabled={!can("sys:role:update")} />
                              </Popconfirm>
                            )
                          }
                        ]}
                      />
                    </div>
                  </Tabs.TabPane>
                </Tabs>
              </Card>
            ) : (
              <div className="app-page__empty-state"><Empty description={t("roles.selectRole")} /></div>
            )}
          </Col>
        </Row>
      </div>

      <Modal title={t("rolesExt.bindUsersToRole")} open={userModalOpen} onCancel={() => setUserModalOpen(false)} onOk={handleAddUsers} okText={t("common.confirm")} cancelText={t("common.cancel")} width={650} destroyOnClose>
        <div style={{ marginBottom: 16 }}>
          <Input placeholder={t("rolesExt.searchUser")} prefix={<SearchOutlined />} value={userSearchText} onChange={(event) => setUserSearchText(event.target.value)} allowClear />
        </div>
        <Table rowKey="userId" size="small" dataSource={filteredModalUsers} pagination={{ pageSize: 6 }} rowSelection={{ selectedRowKeys: selectedUserKeys, onChange: (keys) => setSelectedUserKeys(keys as number[]) }} columns={[{ title: t("rolesExt.displayName"), dataIndex: "displayName" }, { title: t("users.username"), dataIndex: "username" }, { title: t("rolesExt.phone"), dataIndex: "phone" }]} />
      </Modal>

      <Drawer title={editing ? t("roles.drawerTitleEdit") : t("roles.drawerTitleCreate")} open={drawerOpen} onClose={() => setDrawerOpen(false)} width={420} destroyOnClose footer={<div className="app-page__drawer-footer"><Button onClick={() => setDrawerOpen(false)}>{t("common.cancel")}</Button><Button type="primary" loading={saving} onClick={submitBasic}>{t("common.save")}</Button></div>}>
        <Form form={form} layout="vertical">
          <Form.Item label={t("rolesExt.tenantLabel")} name="tenantId" rules={[{ required: true }]} hidden={!isPlatformMode}>
            <Select options={tenants.map((tenant) => ({ label: tenant.tenantName, value: tenant.id }))} disabled={!!editing} />
          </Form.Item>
          <Form.Item label={t("roles.roleName")} name="roleName" rules={[{ required: true }]}>
            <Input placeholder={t("rolesExt.enterRoleName")} />
          </Form.Item>
          <Form.Item label={t("roles.roleCode")} name="roleCode" rules={[{ required: true }]}>
            <Input placeholder={t("rolesExt.roleCodePlaceholder")} disabled={!!editing} />
          </Form.Item>
          <Form.Item label={t("common.status")} name="status" initialValue={1}>
            <Select options={statusDict.map((item) => ({ label: item.itemLabel, value: Number(item.itemValue) }))} />
          </Form.Item>
          <Form.Item label={t("common.remark")} name="remark">
            <Input.TextArea rows={4} placeholder={t("rolesExt.roleScopePlaceholder")} />
          </Form.Item>
        </Form>
      </Drawer>
    </div>
  );
}













