import { useEffect, useState } from 'react'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import {
  Eye,
  KeyRound,
  Loader2,
  Pencil,
  Plus,
  RotateCcw,
  SearchIcon,
} from 'lucide-react'
import { toast } from 'sonner'
import { getApiErrorMessage } from '@/lib/api'
import { hasPermission } from '@/lib/permissions'
import { useAuthStore } from '@/stores/auth-store'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Checkbox } from '@/components/ui/checkbox'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { ScrollArea } from '@/components/ui/scroll-area'
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select'
import {
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
} from '@/components/ui/sheet'
import { Switch } from '@/components/ui/switch'
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from '@/components/ui/table'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { PasswordInput } from '@/components/password-input'
import {
  createAdminUser,
  getUserPermissions,
  listAdminRoles,
  listAdminUsers,
  resetUserPermissions,
  updateAdminUser,
  updateUserPermissions,
  type AdminRole,
  type AdminUser,
} from './api'
import { AdminPage } from './components/admin-page'
import { ListPagination } from './components/list-pagination'
import {
  actionLabels,
  formatDateTime,
  getRoleLabel,
  resourceLabels,
} from './utils'

type CreateUserForm = {
  name: string
  email: string
  password: string
  roleCode: string
  mustChangePassword: boolean
}

type EditUserForm = {
  name: string
  email: string
  roleCode: string
  enabled: boolean
  mustChangePassword: boolean
}

const defaultCreateForm: CreateUserForm = {
  name: '',
  email: '',
  password: '',
  roleCode: 'user',
  mustChangePassword: true,
}

function toEditForm(user: AdminUser): EditUserForm {
  return {
    name: user.name,
    email: user.email,
    roleCode: user.roleCode || 'user',
    enabled: user.enabled,
    mustChangePassword: user.mustChangePassword,
  }
}

function InfoItem({
  label,
  value,
}: {
  label: string
  value?: string | null
}) {
  return (
    <div className='grid gap-1'>
      <div className='text-xs text-muted-foreground'>{label}</div>
      <div className='min-h-8 rounded-md border bg-muted/30 px-3 py-2 text-sm break-all'>
        {value || '-'}
      </div>
    </div>
  )
}

export function AdminUsersPage() {
  const queryClient = useQueryClient()
  const currentUser = useAuthStore((state) => state.auth.user)
  const canWriteUsers = hasPermission(
    currentUser?.permissions,
    'admin/users',
    'write'
  )
  const [page, setPage] = useState(1)
  const [pageSize, setPageSize] = useState(10)
  const [keywordInput, setKeywordInput] = useState('')
  const [keyword, setKeyword] = useState('')
  const [createOpen, setCreateOpen] = useState(false)
  const [selectedUser, setSelectedUser] = useState<AdminUser | null>(null)
  const [activeTab, setActiveTab] = useState('detail')
  const [editForm, setEditForm] = useState<EditUserForm | null>(null)
  const [createForm, setCreateForm] =
    useState<CreateUserForm>(defaultCreateForm)

  const usersQuery = useQuery({
    queryKey: ['admin-users', page, pageSize, keyword],
    queryFn: () => listAdminUsers({ page, pageSize, keyword }),
  })
  const rolesQuery = useQuery({
    queryKey: ['admin-roles'],
    queryFn: listAdminRoles,
  })
  const userPermissionsQuery = useQuery({
    queryKey: ['admin-user-permissions', selectedUser?.id],
    queryFn: () => getUserPermissions(selectedUser!.id),
    enabled: Boolean(selectedUser),
  })

  const refreshUsers = () =>
    queryClient.invalidateQueries({ queryKey: ['admin-users'] })

  const createMutation = useMutation({
    mutationFn: createAdminUser,
    onSuccess: () => {
      toast.success('用户已创建')
      setCreateOpen(false)
      setCreateForm(defaultCreateForm)
      void refreshUsers()
    },
    onError: (error) => toast.error(getApiErrorMessage(error, '创建用户失败')),
  })

  const updateMutation = useMutation({
    mutationFn: ({ id, data }: { id: string; data: EditUserForm }) =>
      updateAdminUser(id, data),
    onSuccess: (user) => {
      toast.success('用户信息已更新')
      setSelectedUser(user)
      setEditForm(toEditForm(user))
      void refreshUsers()
    },
    onError: (error) => toast.error(getApiErrorMessage(error, '保存用户失败')),
  })

  const updatePermissionsMutation = useMutation({
    mutationFn: ({
      id,
      permissions,
    }: {
      id: string
      permissions: Record<string, string[]>
    }) => updateUserPermissions(id, permissions),
    onSuccess: () => {
      toast.success('用户权限已保存')
      void queryClient.invalidateQueries({
        queryKey: ['admin-user-permissions', selectedUser?.id],
      })
    },
    onError: (error) => toast.error(getApiErrorMessage(error, '保存权限失败')),
  })

  const resetPermissionsMutation = useMutation({
    mutationFn: resetUserPermissions,
    onSuccess: () => {
      toast.success('已恢复角色默认权限')
      void queryClient.invalidateQueries({
        queryKey: ['admin-user-permissions', selectedUser?.id],
      })
    },
    onError: (error) =>
      toast.error(getApiErrorMessage(error, '恢复默认权限失败')),
  })

  const users = usersQuery.data?.list ?? []
  const roles = rolesQuery.data ?? []

  useEffect(() => {
    if (selectedUser) {
      setEditForm(toEditForm(selectedUser))
    } else {
      setEditForm(null)
    }
  }, [selectedUser])

  const [permissionDraft, setPermissionDraft] = useState<
    Record<string, string[]>
  >({})

  useEffect(() => {
    const detail = userPermissionsQuery.data
    if (detail) {
      setPermissionDraft(detail.customPermissions ?? detail.effectivePermissions)
    } else {
      setPermissionDraft({})
    }
  }, [userPermissionsQuery.data])

  function handleSearch() {
    setPage(1)
    setKeyword(keywordInput.trim())
  }

  function handleCreate() {
    if (!canWriteUsers) {
      toast.error('当前账号没有新建用户权限')
      return
    }

    createMutation.mutate(createForm)
  }

  function openUser(user: AdminUser, tab: string) {
    setSelectedUser(user)
    setActiveTab(canWriteUsers ? tab : 'detail')
  }

  function handleUpdate() {
    if (!canWriteUsers) {
      toast.error('当前账号没有编辑用户权限')
      return
    }

    if (!selectedUser || !editForm) {
      return
    }

    updateMutation.mutate({ id: selectedUser.id, data: editForm })
  }

  function togglePermission(resource: string, action: string) {
    setPermissionDraft((value) => {
      const actions = new Set(value[resource] ?? [])
      if (actions.has(action)) {
        actions.delete(action)
      } else {
        actions.add(action)
      }

      const next = { ...value, [resource]: Array.from(actions) }
      if (!next[resource].length) {
        delete next[resource]
      }
      return next
    })
  }

  function handleSavePermissions() {
    if (!canWriteUsers) {
      toast.error('当前账号没有配置用户权限')
      return
    }

    if (!selectedUser) {
      return
    }
    updatePermissionsMutation.mutate({
      id: selectedUser.id,
      permissions: permissionDraft,
    })
  }

  function handleResetPermissions() {
    if (!canWriteUsers) {
      toast.error('当前账号没有配置用户权限')
      return
    }

    if (!selectedUser) {
      return
    }
    resetPermissionsMutation.mutate(selectedUser.id)
  }

  return (
    <AdminPage
      title='用户管理'
      description='管理后台账号、基础信息、角色，并支持系统管理员单独设置账号权限。'
      actions={
        canWriteUsers ? (
          <Button onClick={() => setCreateOpen(true)}>
            <Plus />
            新建用户
          </Button>
        ) : null
      }
    >
      <div className='flex flex-col gap-4'>
        <div className='flex flex-wrap items-center gap-2'>
          <Input
            value={keywordInput}
            onChange={(event) => setKeywordInput(event.target.value)}
            onKeyDown={(event) => {
              if (event.key === 'Enter') handleSearch()
            }}
            placeholder='搜索用户名或邮箱'
            className='h-9 w-64'
          />
          <Button variant='outline' onClick={handleSearch}>
            <SearchIcon />
            查询
          </Button>
          <Button
            variant='ghost'
            onClick={() => {
              setKeywordInput('')
              setKeyword('')
              setPage(1)
            }}
          >
            <RotateCcw />
            重置
          </Button>
        </div>

        <div className='overflow-hidden rounded-md border'>
          <Table>
            <TableHeader>
              <TableRow>
                <TableHead>用户</TableHead>
                <TableHead>角色</TableHead>
                <TableHead>状态</TableHead>
                <TableHead>强制改密</TableHead>
                <TableHead>上次登录</TableHead>
                <TableHead>创建时间</TableHead>
                <TableHead className='w-56 text-right'>操作</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {usersQuery.isLoading ? (
                <TableRow>
                  <TableCell colSpan={7} className='h-24 text-center'>
                    <Loader2 className='mx-auto animate-spin' />
                  </TableCell>
                </TableRow>
              ) : users.length ? (
                users.map((user) => (
                  <UserRow
                    key={user.id}
                    user={user}
                    roles={roles}
                    canWrite={canWriteUsers}
                    onOpen={openUser}
                  />
                ))
              ) : (
                <TableRow>
                  <TableCell colSpan={7} className='h-24 text-center'>
                    暂无用户数据
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>

        <ListPagination
          page={usersQuery.data?.page ?? page}
          pageSize={usersQuery.data?.pageSize ?? pageSize}
          total={usersQuery.data?.total ?? 0}
          onPageChange={setPage}
          onPageSizeChange={(nextPageSize) => {
            setPage(1)
            setPageSize(nextPageSize)
          }}
        />
      </div>

      <Dialog open={createOpen} onOpenChange={setCreateOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>新建用户</DialogTitle>
            <DialogDescription>
              新建的账号默认用于后台登录，可按角色控制可访问资源。
            </DialogDescription>
          </DialogHeader>
          <div className='grid gap-4'>
            <div className='grid gap-2'>
              <Label htmlFor='name'>用户名</Label>
              <Input
                id='name'
                value={createForm.name}
                onChange={(event) =>
                  setCreateForm((value) => ({
                    ...value,
                    name: event.target.value,
                  }))
                }
              />
            </div>
            <div className='grid gap-2'>
              <Label htmlFor='email'>邮箱</Label>
              <Input
                id='email'
                value={createForm.email}
                onChange={(event) =>
                  setCreateForm((value) => ({
                    ...value,
                    email: event.target.value,
                  }))
                }
              />
            </div>
            <div className='grid gap-2'>
              <Label htmlFor='password'>初始密码</Label>
              <PasswordInput
                id='password'
                value={createForm.password}
                onChange={(event) =>
                  setCreateForm((value) => ({
                    ...value,
                    password: event.target.value,
                  }))
                }
              />
            </div>
            <div className='grid gap-2'>
              <Label>角色</Label>
              <RoleSelect
                roles={roles}
                value={createForm.roleCode}
                onValueChange={(roleCode) =>
                  setCreateForm((value) => ({ ...value, roleCode }))
                }
              />
            </div>
            <label className='flex items-center gap-3 text-sm'>
              <Switch
                checked={createForm.mustChangePassword}
                onCheckedChange={(mustChangePassword) =>
                  setCreateForm((value) => ({
                    ...value,
                    mustChangePassword,
                  }))
                }
              />
              首次登录后必须修改密码
            </label>
          </div>
          <DialogFooter>
            <Button variant='outline' onClick={() => setCreateOpen(false)}>
              取消
            </Button>
            <Button
              onClick={handleCreate}
              disabled={
                createMutation.isPending ||
                !createForm.name ||
                !createForm.email ||
                !createForm.password
              }
            >
              {createMutation.isPending && <Loader2 className='animate-spin' />}
              保存
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Sheet
        open={!!selectedUser}
        onOpenChange={(open) => {
          if (!open) {
            setSelectedUser(null)
          }
        }}
      >
        <SheetContent className='flex w-full flex-col gap-0 sm:max-w-2xl'>
          <SheetHeader className='border-b text-start'>
            <SheetTitle>用户操作</SheetTitle>
            <SheetDescription>
              查看用户信息、编辑资料，并管理该账号的有效权限。
            </SheetDescription>
          </SheetHeader>

          {selectedUser && editForm && (
            <Tabs value={activeTab} onValueChange={setActiveTab} className='min-h-0 flex-1'>
              <div className='border-b px-4 py-3'>
                <TabsList>
                  <TabsTrigger value='detail'>详情</TabsTrigger>
                  {canWriteUsers && (
                    <TabsTrigger value='edit'>编辑信息</TabsTrigger>
                  )}
                  {canWriteUsers && (
                    <TabsTrigger value='permissions'>权限</TabsTrigger>
                  )}
                </TabsList>
              </div>

              <ScrollArea className='flex-1'>
                <TabsContent value='detail' className='m-0 space-y-4 p-4'>
                  <div className='grid gap-3 sm:grid-cols-2'>
                    <InfoItem label='用户 ID' value={selectedUser.id} />
                    <InfoItem label='用户名' value={selectedUser.name} />
                    <InfoItem label='邮箱' value={selectedUser.email} />
                    <InfoItem
                      label='角色'
                      value={getRoleLabel(selectedUser.roleCode, selectedUser.roleName)}
                    />
                    <InfoItem
                      label='状态'
                      value={selectedUser.enabled ? '启用' : '停用'}
                    />
                    <InfoItem
                      label='强制改密'
                      value={selectedUser.mustChangePassword ? '需要' : '不需要'}
                    />
                    <InfoItem
                      label='上次登录'
                      value={formatDateTime(selectedUser.lastLoginAt)}
                    />
                    <InfoItem
                      label='创建时间'
                      value={formatDateTime(selectedUser.createdAt)}
                    />
                    <InfoItem
                      label='更新时间'
                      value={formatDateTime(selectedUser.updatedAt)}
                    />
                    <InfoItem label='上级用户' value={selectedUser.parentId} />
                  </div>
                </TabsContent>

                <TabsContent value='edit' className='m-0 space-y-4 p-4'>
                  <div className='grid gap-4'>
                    <div className='grid gap-2'>
                      <Label htmlFor='edit-name'>用户名</Label>
                      <Input
                        id='edit-name'
                        value={editForm.name}
                        onChange={(event) =>
                          setEditForm((value) =>
                            value ? { ...value, name: event.target.value } : value
                          )
                        }
                      />
                    </div>
                    <div className='grid gap-2'>
                      <Label htmlFor='edit-email'>邮箱</Label>
                      <Input
                        id='edit-email'
                        value={editForm.email}
                        onChange={(event) =>
                          setEditForm((value) =>
                            value ? { ...value, email: event.target.value } : value
                          )
                        }
                      />
                    </div>
                    <div className='grid gap-2'>
                      <Label>角色</Label>
                      <RoleSelect
                        roles={roles}
                        value={editForm.roleCode}
                        onValueChange={(roleCode) =>
                          setEditForm((value) =>
                            value ? { ...value, roleCode } : value
                          )
                        }
                      />
                    </div>
                    <label className='flex items-center gap-3 text-sm'>
                      <Switch
                        checked={editForm.enabled}
                        onCheckedChange={(enabled) =>
                          setEditForm((value) =>
                            value ? { ...value, enabled } : value
                          )
                        }
                      />
                      账号启用
                    </label>
                    <label className='flex items-center gap-3 text-sm'>
                      <Switch
                        checked={editForm.mustChangePassword}
                        onCheckedChange={(mustChangePassword) =>
                          setEditForm((value) =>
                            value ? { ...value, mustChangePassword } : value
                          )
                        }
                      />
                      下次登录必须修改密码
                    </label>
                  </div>
                  <div className='flex justify-end gap-2 border-t pt-4'>
                    <Button
                      variant='outline'
                      onClick={() => setEditForm(toEditForm(selectedUser))}
                      disabled={updateMutation.isPending}
                    >
                      还原
                    </Button>
                    <Button
                      onClick={handleUpdate}
                      disabled={
                        updateMutation.isPending ||
                        !editForm.name ||
                        !editForm.email ||
                        !editForm.roleCode
                      }
                    >
                      {updateMutation.isPending && (
                        <Loader2 className='animate-spin' />
                      )}
                      保存修改
                    </Button>
                  </div>
                </TabsContent>

                <TabsContent value='permissions' className='m-0 space-y-4 p-4'>
                  <div className='rounded-md border bg-muted/30 p-3 text-sm'>
                    <div>
                      当前角色：
                      <span className='ml-1 font-medium'>
                        {getRoleLabel(editForm.roleCode)}
                      </span>
                    </div>
                    <div className='mt-1 text-muted-foreground'>
                      {userPermissionsQuery.data?.isCustom
                        ? '当前用户正在使用自定义权限，优先级高于角色默认权限。'
                        : '当前用户使用角色默认权限。系统管理员可以为用户单独设置权限。'}
                    </div>
                  </div>
                  <div className='overflow-hidden rounded-md border'>
                    <Table>
                      <TableHeader>
                        <TableRow>
                          <TableHead>资源</TableHead>
                          <TableHead>用户权限</TableHead>
                          <TableHead>角色默认</TableHead>
                        </TableRow>
                      </TableHeader>
                      <TableBody>
                        {userPermissionsQuery.isLoading ? (
                          <TableRow>
                            <TableCell colSpan={3} className='h-20 text-center'>
                              <Loader2 className='mx-auto animate-spin' />
                            </TableCell>
                          </TableRow>
                        ) : userPermissionsQuery.data?.resources.length ? (
                          userPermissionsQuery.data.resources.map((resource) => {
                            const userActions =
                              permissionDraft[resource.resource] ?? []
                            const roleActions =
                              userPermissionsQuery.data.rolePermissions[
                                resource.resource
                              ] ?? []
                            const canEdit =
                              userPermissionsQuery.data.canEdit &&
                              !updatePermissionsMutation.isPending &&
                              !resetPermissionsMutation.isPending
                            return (
                              <TableRow key={resource.resource}>
                                <TableCell>
                                  <div className='font-medium'>
                                    {resourceLabels[resource.resource] ||
                                      resource.name}
                                  </div>
                                  <div className='text-xs text-muted-foreground'>
                                    {resource.resource}
                                  </div>
                                </TableCell>
                                <TableCell>
                                  <div className='flex flex-wrap gap-3'>
                                    {resource.actions.map((action) => (
                                      <label
                                        key={action}
                                        className='flex items-center gap-2 text-sm'
                                      >
                                        <Checkbox
                                          checked={userActions.includes(action)}
                                          disabled={!canEdit}
                                          onCheckedChange={() =>
                                            togglePermission(
                                              resource.resource,
                                              action
                                            )
                                          }
                                        />
                                        {actionLabels[action] || action}
                                      </label>
                                    ))}
                                  </div>
                                </TableCell>
                                <TableCell>
                                  <div className='flex flex-wrap gap-2'>
                                    {resource.actions.map((action) => (
                                      <Badge
                                        key={action}
                                        variant={
                                          roleActions.includes(action)
                                            ? 'outline'
                                            : 'secondary'
                                        }
                                      >
                                        {actionLabels[action] || action}
                                        {roleActions.includes(action)
                                          ? '：有'
                                          : '：无'}
                                      </Badge>
                                    ))}
                                  </div>
                                </TableCell>
                              </TableRow>
                            )
                          })
                        ) : (
                          <TableRow>
                            <TableCell colSpan={3} className='h-20 text-center'>
                              暂无权限资源
                            </TableCell>
                          </TableRow>
                        )}
                      </TableBody>
                    </Table>
                  </div>
                  <div className='flex flex-wrap items-center justify-between gap-3'>
                    <div className='text-sm text-muted-foreground'>
                      普通用户使用默认权限；只有系统管理员可以为账号单独设置权限。
                    </div>
                    {userPermissionsQuery.data?.canEdit && (
                      <div className='flex gap-2'>
                        <Button
                          variant='outline'
                          onClick={() => {
                            const detail = userPermissionsQuery.data
                            if (detail) {
                              setPermissionDraft(
                                detail.customPermissions ??
                                  detail.effectivePermissions
                              )
                            }
                          }}
                          disabled={
                            updatePermissionsMutation.isPending ||
                            resetPermissionsMutation.isPending
                          }
                        >
                          还原修改
                        </Button>
                        <Button
                          variant='outline'
                          onClick={handleResetPermissions}
                          disabled={
                            resetPermissionsMutation.isPending ||
                            updatePermissionsMutation.isPending ||
                            !userPermissionsQuery.data.isCustom
                          }
                        >
                          {resetPermissionsMutation.isPending && (
                            <Loader2 className='animate-spin' />
                          )}
                          恢复角色默认
                        </Button>
                        <Button
                          onClick={handleSavePermissions}
                          disabled={
                            updatePermissionsMutation.isPending ||
                            resetPermissionsMutation.isPending
                          }
                        >
                          {updatePermissionsMutation.isPending && (
                            <Loader2 className='animate-spin' />
                          )}
                          保存权限
                        </Button>
                      </div>
                    )}
                  </div>
                </TabsContent>
              </ScrollArea>
            </Tabs>
          )}
        </SheetContent>
      </Sheet>
    </AdminPage>
  )
}

function RoleSelect({
  roles,
  value,
  onValueChange,
}: {
  roles: AdminRole[]
  value: string
  onValueChange: (value: string) => void
}) {
  return (
    <Select value={value} onValueChange={onValueChange}>
      <SelectTrigger className='w-full'>
        <SelectValue placeholder='选择角色' />
      </SelectTrigger>
      <SelectContent>
        {roles.map((role) => (
          <SelectItem key={role.code} value={role.code}>
            {getRoleLabel(role.code, role.name)}
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  )
}

function UserRow({
  user,
  roles,
  canWrite,
  onOpen,
}: {
  user: AdminUser
  roles: AdminRole[]
  canWrite: boolean
  onOpen: (user: AdminUser, tab: string) => void
}) {
  const role = roles.find((item) => item.code === user.roleCode)

  return (
    <TableRow>
      <TableCell>
        <div className='font-medium'>{user.name}</div>
        <div className='text-xs text-muted-foreground'>{user.email}</div>
      </TableCell>
      <TableCell>
        <Badge variant='outline'>
          {getRoleLabel(user.roleCode, role?.name || user.roleName)}
        </Badge>
      </TableCell>
      <TableCell>
        <Badge variant={user.enabled ? 'default' : 'secondary'}>
          {user.enabled ? '启用' : '停用'}
        </Badge>
      </TableCell>
      <TableCell>
        <Badge variant={user.mustChangePassword ? 'default' : 'outline'}>
          {user.mustChangePassword ? '需要' : '不需要'}
        </Badge>
      </TableCell>
      <TableCell>{formatDateTime(user.lastLoginAt)}</TableCell>
      <TableCell>{formatDateTime(user.createdAt)}</TableCell>
      <TableCell className='text-right'>
        <div className='flex justify-end gap-1'>
          <Button
            type='button'
            size='sm'
            variant='ghost'
            onClick={() => onOpen(user, 'detail')}
          >
            <Eye />
            查看
          </Button>
          {canWrite && (
            <Button
              type='button'
              size='sm'
              variant='ghost'
              onClick={() => onOpen(user, 'edit')}
            >
              <Pencil />
              编辑
            </Button>
          )}
          {canWrite && (
            <Button
              type='button'
              size='sm'
              variant='ghost'
              onClick={() => onOpen(user, 'permissions')}
            >
              <KeyRound />
              权限
            </Button>
          )}
        </div>
      </TableCell>
    </TableRow>
  )
}
