import { Button, Card, Col, Empty, Input, Row, Space, Table, Tag, Tree, Typography, App } from 'antd';
import type { DataNode } from "antd/es/tree";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { ClusterOutlined, KeyOutlined, SafetyCertificateOutlined, SaveOutlined, SearchOutlined } from "@ant-design/icons";
import { listPermissions, listRolePermissions, listRoles, saveRolePermissions } from "@/api";
import PageHeader from "@/components/shared/PageHeader";
import { getStandardPagination } from "@/utils/pagination";
import type { SysPermission, SysRole } from "@/types";

const { Text } = Typography;

type PermissionNode = SysPermission & { key: number; children?: PermissionNode[] };

function buildPermissionTree(list: SysPermission[]): PermissionNode[] {
  if (!list.length) return [];
  const active = list.filter((item) => item.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) => {
      if (node.children?.length) {
        sortNodes(node.children);
      }
    });
  };

  sortNodes(roots);
  return roots;
}

function toTreeData(nodes: PermissionNode[]): DataNode[] {
  return nodes.map((node) => ({
    key: node.permId,
    title: (
      <Space>
        <span>{node.name}</span>
        {node.permType === "button" ? (
          <Tag color="blue" style={{ marginLeft: 4 }}>
            Button
          </Tag>
        ) : null}
      </Space>
    ),
    children: node.children?.length ? toTreeData(node.children) : undefined
  }));
}

export default function RolePermissionBinding() {
  const { message } = App.useApp();
  const { t } = useTranslation();
  const [roles, setRoles] = useState<SysRole[]>([]);
  const [permissions, setPermissions] = useState<SysPermission[]>([]);
  const [loadingRoles, setLoadingRoles] = useState(false);
  const [loadingPerms, setLoadingPerms] = useState(false);
  const [saving, setSaving] = useState(false);
  const [selectedRoleId, setSelectedRoleId] = useState<number | null>(null);
  const [checkedPermIds, setCheckedPermIds] = useState<number[]>([]);
  const [halfCheckedIds, setHalfCheckedIds] = useState<number[]>([]);
  const [searchText, setSearchText] = useState("");

  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 selectedRole = useMemo(
    () => roles.find((role) => role.roleId === selectedRoleId) || null,
    [roles, selectedRoleId]
  );

  const filteredRoles = useMemo(() => {
    if (!searchText) {
      return roles;
    }
    const lower = searchText.toLowerCase();
    return roles.filter((role) => role.roleName.toLowerCase().includes(lower) || role.roleCode.toLowerCase().includes(lower));
  }, [roles, searchText]);

  const treeData = useMemo(() => toTreeData(buildPermissionTree(permissions)), [permissions]);

  const loadRoles = async () => {
    setLoadingRoles(true);
    try {
      const list = await listRoles();
      setRoles(list || []);
    } finally {
      setLoadingRoles(false);
    }
  };

  const loadPermissions = async () => {
    setLoadingPerms(true);
    try {
      const list = await listPermissions();
      setPermissions(list || []);
    } finally {
      setLoadingPerms(false);
    }
  };

  const loadRolePermissions = async (roleId: number) => {
    try {
      const list = await listRolePermissions(roleId);
      const normalized = (list || []).map((id) => Number(id)).filter((id) => !Number.isNaN(id));
      const leafIds = normalized.filter((id) => !permissions.some((permission) => permission.parentId === id));
      setCheckedPermIds(leafIds);
      setHalfCheckedIds([]);
    } catch {
      setCheckedPermIds([]);
      setHalfCheckedIds([]);
    }
  };

  useEffect(() => {
    loadRoles();
    loadPermissions();
  }, []);

  useEffect(() => {
    if (selectedRoleId && permissions.length > 0) {
      loadRolePermissions(selectedRoleId);
    } else {
      setCheckedPermIds([]);
      setHalfCheckedIds([]);
    }
  }, [selectedRoleId, permissions]);

  const handleSave = async () => {
    if (!selectedRoleId) {
      message.warning(t("rolePerm.selectRole"));
      return;
    }
    setSaving(true);
    try {
      await saveRolePermissions(selectedRoleId, Array.from(new Set([...checkedPermIds, ...halfCheckedIds])));
      message.success(t("common.success"));
    } finally {
      setSaving(false);
    }
  };

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

      <div className="app-page__page-actions">
        <Button
          type="primary"
          icon={<SaveOutlined aria-hidden="true" />}
          onClick={handleSave}
          loading={saving}
          disabled={!selectedRoleId || (selectedRole?.roleCode === "TENANT_ADMIN" && !isPlatformMode)}
        >
          {saving ? t("common.loading") : t("common.save")}
        </Button>
      </div>

      <Row gutter={24} className="app-page__split" style={{ height: "calc(100vh - 180px)" }}>
        <Col xs={24} lg={10} style={{ height: "100%" }}>
          <Card title={<Space><SafetyCertificateOutlined aria-hidden="true" /><span>{t("rolePerm.roleList")}</span></Space>} className="app-page__panel-card full-height-card" styles={{ body: { height: "100%", display: "flex", flexDirection: "column", overflow: "hidden" } }}>
            <div className="mb-4">
              <Input
                placeholder={t("rolePerm.searchRole")}
                prefix={<SearchOutlined aria-hidden="true" className="text-gray-400" />}
                value={searchText}
                onChange={(event) => setSearchText(event.target.value)}
                allowClear
                aria-label={t("rolePerm.searchRole")}
              />
            </div>
            <div style={{ flex: 1, minHeight: 0 }}>
              <Table
                rowKey="roleId"
                size="middle"
                loading={loadingRoles}
                dataSource={filteredRoles}
                scroll={{ y: "calc(100vh - 370px)" }}
                rowSelection={{
                  type: "radio",
                  selectedRowKeys: selectedRoleId ? [selectedRoleId] : [],
                  onChange: (keys) => setSelectedRoleId(keys[0] as number)
                }}
                onRow={(record) => ({
                  onClick: () => setSelectedRoleId(record.roleId),
                  className: "cursor-pointer"
                })}
                pagination={getStandardPagination(filteredRoles.length, 1, 10)}
                columns={[
                  {
                    title: t("roles.roleName"),
                    key: "role",
                    render: (_, record: SysRole) => (
                      <div className="min-w-0">
                        <div style={{ fontWeight: 500 }} className="truncate">{record.roleName}</div>
                        <div style={{ fontSize: 12, color: "#8c8c8c" }} className="truncate tabular-nums">{record.roleCode}</div>
                      </div>
                    )
                  },
                  {
                    title: t("common.status"),
                    dataIndex: "status",
                    width: 80,
                    render: (value: number) => (value === 1 ? <Tag color="green" className="m-0">鍚敤</Tag> : <Tag className="m-0">绂佺敤</Tag>)
                  }
                ]}
              />
            </div>
          </Card>
        </Col>

        <Col xs={24} lg={14} style={{ height: "100%" }}>
          <Card
            title={<Space><KeyOutlined aria-hidden="true" /><span>{t("rolePerm.permConfig")}</span></Space>}
            className="app-page__panel-card full-height-card"
            styles={{ body: { height: "100%", display: "flex", flexDirection: "column", overflow: "hidden" } }}
            extra={selectedRole ? <Tag color="blue">{t("rolePerm.currentRole")}: {selectedRole.roleName}</Tag> : null}
          >
            {selectedRoleId ? (
              <div className="role-permission-tree-container" style={{ padding: "8px 0", height: "100%", overflowY: "auto" }}>
                <Tree
                  checkable
                  selectable={false}
                  checkStrictly={false}
                  treeData={treeData}
                  checkedKeys={checkedPermIds}
                  onCheck={(keys, info) => {
                    const checked = Array.isArray(keys) ? keys : keys.checked;
                    const halfChecked = info.halfCheckedKeys || [];
                    setCheckedPermIds(checked.map((key) => Number(key)));
                    setHalfCheckedIds(halfChecked.map((key) => Number(key)));
                  }}
                  defaultExpandAll
                />
                {!permissions.length && !loadingPerms ? <Empty description="鏆傛棤鏉冮檺鏁版嵁" /> : null}
              </div>
            ) : (
              <div className="flex flex-col items-center justify-center py-20 bg-gray-50 rounded-lg border border-dashed border-gray-200">
                <ClusterOutlined style={{ fontSize: 40, color: "#bfbfbf", marginBottom: 16 }} aria-hidden="true" />
                <Text type="secondary">{t("rolePerm.selectRole")}</Text>
              </div>
            )}
          </Card>
        </Col>
      </Row>
    </div>
  );
}
