import { useEffect, useMemo, useState } from 'react'
import {
  Button,
  Card,
  Drawer,
  Form,
  Input,
  Modal,
  Select,
  Space,
  Table,
  Tabs,
  Tag,
  Tree,
  Typography,
  message,
} from 'antd'
import type { ColumnsType } from 'antd/es/table'
import type { DataNode } from 'antd/es/tree'
import { apiRegistryApi, authorityApi, casbinApi, menuApi, userApi } from '@/lib/api'
import { collectCheckedLeafMenus, flattenAuthorities } from '@/lib/tree'
import type { ApiRecord, Authority, MenuNode, UserInfo } from '@/types/system'

type PermissionTab = 'menus' | 'apis' | 'users'

function mapMenusToTree(menus: MenuNode[]): DataNode[] {
  return menus.map((menu) => ({
    key: menu.ID,
    title: menu.meta.title,
    children: mapMenusToTree(menu.children || []),
  }))
}

function mapApisToTree(apis: ApiRecord[]): DataNode[] {
  const grouped = apis.reduce<Record<string, ApiRecord[]>>((accumulator, api) => {
    if (!accumulator[api.apiGroup]) {
      accumulator[api.apiGroup] = []
    }
    accumulator[api.apiGroup].push(api)
    return accumulator
  }, {})

  return Object.entries(grouped).map(([group, items]) => ({
    key: `group:${group}`,
    title: `${group} 组`,
    children: items.map((item) => ({
      key: `${item.path}::${item.method}`,
      title: `${item.method} ${item.path} · ${item.description}`,
    })),
  }))
}

export function RoleManagementPage() {
  const [form] = Form.useForm()
  const [roles, setRoles] = useState<Authority[]>([])
  const [menuTree, setMenuTree] = useState<MenuNode[]>([])
  const [apis, setApis] = useState<ApiRecord[]>([])
  const [users, setUsers] = useState<UserInfo[]>([])
  const [roleModalOpen, setRoleModalOpen] = useState(false)
  const [drawerOpen, setDrawerOpen] = useState(false)
  const [savingRole, setSavingRole] = useState(false)
  const [loading, setLoading] = useState(false)
  const [activeTab, setActiveTab] = useState<PermissionTab>('menus')
  const [editingRole, setEditingRole] = useState<Authority | null>(null)
  const [copySource, setCopySource] = useState<Authority | null>(null)
  const [activeRole, setActiveRole] = useState<Authority | null>(null)
  const [menuChecked, setMenuChecked] = useState<number[]>([])
  const [defaultRouter, setDefaultRouter] = useState<string>()
  const [apiChecked, setApiChecked] = useState<string[]>([])
  const [userIds, setUserIds] = useState<number[]>([])
  const [savingPermission, setSavingPermission] = useState(false)

  const roleOptions = useMemo(
    () =>
      flattenAuthorities(roles).map((item) => ({
        label: `${'　'.repeat(item.depth)}${item.authorityName} (${item.authorityId})`,
        value: item.authorityId,
      })),
    [roles],
  )

  const reloadRoles = async () => {
    setLoading(true)
    try {
      const response = await authorityApi.getAuthorityList()
      setRoles(response.data)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    reloadRoles()
  }, [])

  const openCreate = (parentId?: number) => {
    setEditingRole(null)
    setCopySource(null)
    form.resetFields()
    form.setFieldsValue({ parentId: parentId ?? 0 })
    setRoleModalOpen(true)
  }

  const openEdit = (record: Authority) => {
    setEditingRole(record)
    setCopySource(null)
    form.setFieldsValue({
      authorityId: record.authorityId,
      authorityName: record.authorityName,
      parentId: record.parentId ?? 0,
    })
    setRoleModalOpen(true)
  }

  const openCopy = (record: Authority) => {
    setEditingRole(null)
    setCopySource(record)
    form.setFieldsValue({
      authorityId: undefined,
      authorityName: `${record.authorityName}-副本`,
      parentId: record.parentId ?? 0,
    })
    setRoleModalOpen(true)
  }

  const saveRole = async () => {
    const values = await form.validateFields()
    setSavingRole(true)
    try {
      if (copySource) {
        await authorityApi.copyAuthority({
          oldAuthorityId: copySource.authorityId,
          authority: {
            authorityId: values.authorityId,
            authorityName: values.authorityName,
            parentId: values.parentId,
          },
        })
        message.success('角色已复制')
      } else if (editingRole) {
        await authorityApi.updateAuthority({
          authorityId: editingRole.authorityId,
          authorityName: values.authorityName,
          parentId: values.parentId,
          defaultRouter: editingRole.defaultRouter,
        })
        message.success('角色已更新')
      } else {
        await authorityApi.createAuthority({
          authorityId: values.authorityId,
          authorityName: values.authorityName,
          parentId: values.parentId,
        })
        message.success('角色已创建')
      }

      setRoleModalOpen(false)
      reloadRoles()
    } finally {
      setSavingRole(false)
    }
  }

  const deleteRole = (record: Authority) => {
    Modal.confirm({
      title: `删除角色 ${record.authorityName}`,
      content: '删除前请确认没有用户正在依赖该角色。',
      okButtonProps: { danger: true },
      onOk: async () => {
        await authorityApi.deleteAuthority(record.authorityId)
        message.success('角色已删除')
        reloadRoles()
      },
    })
  }

  const openPermissionDrawer = async (record: Authority) => {
    setActiveRole(record)
    setDrawerOpen(true)
    const [menuRes, checkedMenusRes, apiRes, policyRes, userRes, roleUserRes] = await Promise.all([
      menuApi.getBaseMenuTree(),
      menuApi.getMenuAuthority(record.authorityId),
      apiRegistryApi.getAllApis(),
      casbinApi.getPolicyPathByAuthorityId(record.authorityId),
      userApi.getUserList({ page: 1, pageSize: 999 }),
      authorityApi.getUsersByAuthorityId(record.authorityId),
    ])

    setMenuTree(menuRes.data.menus)
    setMenuChecked(
      checkedMenusRes.data.menus.map((item) => Number((item as unknown as { menuId?: number; ID: number }).menuId ?? item.ID)),
    )
    setDefaultRouter(record.defaultRouter)
    setApis(apiRes.data.apis)
    setApiChecked(policyRes.data.paths.map((item) => `${item.path}::${item.method}`))
    setUsers(userRes.data.list)
    setUserIds(roleUserRes.data)
  }

  const saveCurrentPermission = async () => {
    if (!activeRole) {
      return
    }
    setSavingPermission(true)
    try {
      if (activeTab === 'menus') {
        const checkedMenus = collectCheckedLeafMenus(menuTree, new Set(menuChecked))
        await menuApi.addMenuAuthority({
          authorityId: activeRole.authorityId,
          menus: checkedMenus,
        })
        await authorityApi.updateAuthority({
          authorityId: activeRole.authorityId,
          authorityName: activeRole.authorityName,
          parentId: activeRole.parentId,
          defaultRouter,
        })
        message.success('菜单权限已保存')
      } else if (activeTab === 'apis') {
        const selectedApis = apis
          .filter((item) => apiChecked.includes(`${item.path}::${item.method}`))
          .map((item) => ({ path: item.path, method: item.method }))
        await casbinApi.updateCasbin({
          authorityId: activeRole.authorityId,
          casbinInfos: selectedApis,
        })
        message.success('API 权限已保存')
      } else {
        await authorityApi.setRoleUsers({
          authorityId: activeRole.authorityId,
          userIds,
        })
        message.success('角色用户关系已保存')
      }
      reloadRoles()
    } finally {
      setSavingPermission(false)
    }
  }

  const menuOptions = useMemo(
    () =>
      collectCheckedLeafMenus(menuTree, new Set(menuChecked)).map((menu) => ({
        label: menu.meta.title,
        value: menu.name,
      })),
    [menuChecked, menuTree],
  )

  const columns: ColumnsType<Authority> = [
    {
      title: '角色 ID',
      dataIndex: 'authorityId',
      width: 120,
    },
    {
      title: '角色名称',
      dataIndex: 'authorityName',
      width: 200,
    },
    {
      title: '默认首页',
      dataIndex: 'defaultRouter',
      width: 140,
      render: (value: string | undefined) => value || '-',
    },
    {
      title: '操作',
      key: 'actions',
      width: 320,
      render: (_, record) => (
        <Space wrap>
          <Button type="link" onClick={() => openPermissionDrawer(record)}>
            设置权限
          </Button>
          <Button type="link" onClick={() => openCreate(record.authorityId)}>
            新增子角色
          </Button>
          <Button type="link" onClick={() => openCopy(record)}>
            复制
          </Button>
          <Button type="link" onClick={() => openEdit(record)}>
            编辑
          </Button>
          <Button danger type="link" onClick={() => deleteRole(record)}>
            删除
          </Button>
        </Space>
      ),
    },
  ]

  return (
    <div className="page-stack">
      <Card className="glass-panel page-panel">
        <div className="section-heading">
          <div>
            <Typography.Title level={2} style={{ marginBottom: 8 }}>
              角色管理
            </Typography.Title>
            <Typography.Paragraph className="text-muted" style={{ marginBottom: 0 }}>
              当前页接通角色树、菜单授权、API 授权和角色用户绑定。
            </Typography.Paragraph>
          </div>
          <Button type="primary" onClick={() => openCreate()}>
            新建角色
          </Button>
        </div>
        <Table
          rowKey="authorityId"
          loading={loading}
          columns={columns}
          dataSource={roles}
          expandable={{ defaultExpandAllRows: true }}
          pagination={false}
        />
      </Card>

      <Modal
        open={roleModalOpen}
        title={copySource ? `复制角色 · ${copySource.authorityName}` : editingRole ? '编辑角色' : '新建角色'}
        onCancel={() => setRoleModalOpen(false)}
        onOk={saveRole}
        confirmLoading={savingRole}
      >
        <Form form={form} layout="vertical">
          <Form.Item name="parentId" label="父角色">
            <Select options={[{ label: '根角色', value: 0 }, ...roleOptions]} />
          </Form.Item>
          <Form.Item name="authorityId" label="角色 ID" rules={[{ required: true, message: '请输入角色 ID' }]}>
            <Input />
          </Form.Item>
          <Form.Item name="authorityName" label="角色名称" rules={[{ required: true, message: '请输入角色名称' }]}>
            <Input />
          </Form.Item>
        </Form>
      </Modal>

      <Drawer
        open={drawerOpen}
        onClose={() => setDrawerOpen(false)}
        width={900}
        title={activeRole ? `角色权限 · ${activeRole.authorityName}` : '角色权限'}
        extra={
          <Button type="primary" loading={savingPermission} onClick={saveCurrentPermission}>
            保存当前标签
          </Button>
        }
      >
        <Tabs activeKey={activeTab} onChange={(key) => setActiveTab(key as PermissionTab)}>
          <Tabs.TabPane tab="菜单权限" key="menus">
            <Space direction="vertical" style={{ width: '100%' }} size="large">
              <Select
                value={defaultRouter}
                options={menuOptions}
                allowClear
                placeholder="请选择默认首页"
                onChange={(value) => setDefaultRouter(value)}
              />
              <Tree
                checkable
                defaultExpandAll
                checkedKeys={menuChecked}
                treeData={mapMenusToTree(menuTree)}
                onCheck={(checkedKeys) => setMenuChecked((checkedKeys as number[]).map((item) => Number(item)))}
              />
            </Space>
          </Tabs.TabPane>
          <Tabs.TabPane tab="API 权限" key="apis">
            <Tree
              checkable
              defaultExpandAll
              checkedKeys={apiChecked}
              treeData={mapApisToTree(apis)}
              onCheck={(checkedKeys) => setApiChecked((checkedKeys as string[]).filter((item) => !item.startsWith('group:')))}
            />
          </Tabs.TabPane>
          <Tabs.TabPane tab="角色用户" key="users">
            <Select
              mode="multiple"
              style={{ width: '100%' }}
              value={userIds}
              options={users.map((user) => ({
                label: `${user.nickName} (${user.userName})`,
                value: user.ID,
              }))}
              onChange={(value) => setUserIds(value)}
            />
            <div style={{ marginTop: 12 }}>
              <Tag>{userIds.length} 个用户已绑定到当前角色</Tag>
            </div>
          </Tabs.TabPane>
        </Tabs>
      </Drawer>
    </div>
  )
}
