import { createFileRoute } from '@tanstack/react-router'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useState } from 'react'
import { api } from '@/lib/api-client'
import { userListOptions, userRolesOptions, userMutations, type UserRecord } from '@/api/users'
import { roleListOptions, rbacMutations } from '@/api/rbac'
import { usePagination } from '@/hooks/use-pagination'
import { DataTable, type Column } from '@/components/shared/data-table'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { MoreVertical, Shield, Plus, X, KeyRound, Search, UserCheck, UserX } from 'lucide-react'
import { toast } from 'sonner'
import { useAuthStore } from '@/stores/auth.store'

export const Route = createFileRoute('/_authenticated/users')({
  validateSearch: (search: Record<string, unknown>) => ({
    page: Number(search.page) || 1,
    limit: Number(search.limit) || 25,
    q: (search.q as string) || undefined,
    sort: (search.sort as string) || undefined,
    order: (search.order as 'asc' | 'desc') || 'asc',
  }),
  component: UsersPage,
})

function ManageRolesDialog({ user, open, onClose }: { user: UserRecord; open: boolean; onClose: () => void }) {
  const queryClient = useQueryClient()
  const { data: userRolesData } = useQuery(userRolesOptions(user.id))
  const { data: allRolesData } = useQuery(roleListOptions())
  const [selectedRoleId, setSelectedRoleId] = useState('')

  const userRoles = userRolesData?.data ?? []
  const allRoles = allRolesData?.data ?? []
  const assignedIds = new Set(userRoles.map((r) => r.id))
  const availableRoles = allRoles.filter((r) => !assignedIds.has(r.id))

  const assignMutation = useMutation({
    mutationFn: (roleId: string) => rbacMutations.assignRole(user.id, roleId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['users'] })
      setSelectedRoleId('')
      toast.success('Role assigned')
    },
    onError: (err) => toast.error(err.message),
  })

  const removeMutation = useMutation({
    mutationFn: (roleId: string) => rbacMutations.removeRole(user.id, roleId),
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['users'] })
      toast.success('Role removed')
    },
    onError: (err) => toast.error(err.message),
  })

  return (
    <Dialog open={open} onOpenChange={(o) => !o && onClose()}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Manage Roles — {user.firstName} {user.lastName}</DialogTitle>
        </DialogHeader>

        <div className="space-y-4">
          <div className="space-y-2">
            <p className="text-sm font-medium">Assigned Roles</p>
            {userRoles.length === 0 ? (
              <p className="text-sm text-muted-foreground">No roles assigned</p>
            ) : (
              <div className="space-y-1">
                {userRoles.map((r) => (
                  <div key={r.id} className="flex items-center justify-between p-2 rounded-md border">
                    <div className="flex items-center gap-2">
                      <Shield className="h-4 w-4 text-muted-foreground" />
                      <span className="text-sm font-medium">{r.name}</span>
                      {r.isSystem && <Badge variant="secondary" className="text-xs">System</Badge>}
                    </div>
                    <Button variant="ghost" size="sm" className="h-6 w-6 p-0" onClick={() => removeMutation.mutate(r.id)}>
                      <X className="h-3 w-3 text-destructive" />
                    </Button>
                  </div>
                ))}
              </div>
            )}
          </div>

          {availableRoles.length > 0 && (
            <div className="flex gap-2">
              <Select value={selectedRoleId} onValueChange={setSelectedRoleId}>
                <SelectTrigger className="flex-1">
                  <SelectValue placeholder="Select a role to add" />
                </SelectTrigger>
                <SelectContent>
                  {availableRoles.map((r) => (
                    <SelectItem key={r.id} value={r.id}>{r.name}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
              <Button
                size="sm"
                disabled={!selectedRoleId || assignMutation.isPending}
                onClick={() => selectedRoleId && assignMutation.mutate(selectedRoleId)}
              >
                <Plus className="h-4 w-4" />
              </Button>
            </div>
          )}
        </div>
      </DialogContent>
    </Dialog>
  )
}

function UsersPage() {
  const queryClient = useQueryClient()
  const hasPermission = useAuthStore((s) => s.hasPermission)
  const { params, setPage, setSearch, setSort } = usePagination()
  const [searchInput, setSearchInput] = useState(params.q ?? '')
  const [managingUser, setManagingUser] = useState<UserRecord | null>(null)

  const { data, isLoading } = useQuery(userListOptions(params))

  const statusMutation = useMutation({
    mutationFn: ({ userId, isActive }: { userId: string; isActive: boolean }) =>
      userMutations.toggleStatus(userId, isActive),
    onSuccess: (_data, vars) => {
      queryClient.invalidateQueries({ queryKey: ['users'] })
      toast.success(vars.isActive ? 'User enabled' : 'User disabled')
    },
    onError: (err) => toast.error(err.message),
  })

  function handleSearchSubmit(e: React.FormEvent) {
    e.preventDefault()
    setSearch(searchInput)
  }

  const userColumns: Column<UserRecord>[] = [
    {
      key: 'name',
      header: 'Name',
      sortable: true,
      render: (row) => (
        <span className={`font-medium ${!row.isActive ? 'text-muted-foreground' : ''}`}>
          {row.firstName} {row.lastName}
        </span>
      ),
    },
    {
      key: 'email',
      header: 'Email',
      sortable: true,
      render: (row) => <span className={!row.isActive ? 'text-muted-foreground' : ''}>{row.email}</span>,
    },
    {
      key: 'roles',
      header: 'Roles',
      render: (row) =>
        row.roles.length === 0 ? (
          <span className="text-sm text-muted-foreground">No roles</span>
        ) : (
          <div className="flex flex-wrap gap-1">
            {row.roles.map((r) => (
              <Badge key={r.id} variant={r.isSystem ? 'secondary' : 'default'} className="text-xs">
                {r.name}
              </Badge>
            ))}
          </div>
        ),
    },
    {
      key: 'status',
      header: 'Status',
      render: (row) =>
        row.isActive ? (
          <Badge variant="secondary" className="text-xs">Active</Badge>
        ) : (
          <Badge variant="destructive" className="text-xs">Disabled</Badge>
        ),
    },
    {
      key: 'created_at',
      header: 'Created',
      sortable: true,
      render: (row) => new Date(row.createdAt).toLocaleDateString(),
    },
    {
      key: 'actions',
      header: '',
      render: (row) => (
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="ghost" size="sm" className="h-8 w-8 p-0">
              <MoreVertical className="h-4 w-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            {hasPermission('users.edit') && (
              <DropdownMenuItem onClick={() => setManagingUser(row)}>
                <Shield className="mr-2 h-4 w-4" />
                Manage Roles
              </DropdownMenuItem>
            )}
            {hasPermission('users.admin') && (
              <DropdownMenuItem onClick={async () => {
                try {
                  const res = await api.post<{ resetLink: string }>(`/v1/auth/reset-password/${row.id}`, {})
                  await navigator.clipboard.writeText(res.resetLink)
                  toast.success('Reset link copied to clipboard')
                } catch (err) {
                  toast.error(err instanceof Error ? err.message : 'Failed to generate link')
                }
              }}>
                <KeyRound className="mr-2 h-4 w-4" />
                Reset Password Link
              </DropdownMenuItem>
            )}
            {hasPermission('users.admin') && (
              <DropdownMenuItem
                onClick={() => statusMutation.mutate({ userId: row.id, isActive: !row.isActive })}
              >
                {row.isActive ? (
                  <>
                    <UserX className="mr-2 h-4 w-4" />
                    Disable User
                  </>
                ) : (
                  <>
                    <UserCheck className="mr-2 h-4 w-4" />
                    Enable User
                  </>
                )}
              </DropdownMenuItem>
            )}
          </DropdownMenuContent>
        </DropdownMenu>
      ),
    },
  ]

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold">Users</h1>

      {managingUser && (
        <ManageRolesDialog user={managingUser} open={!!managingUser} onClose={() => setManagingUser(null)} />
      )}

      <form onSubmit={handleSearchSubmit} className="flex gap-2 max-w-sm">
        <div className="relative flex-1">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
          <Input
            placeholder="Search users..."
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
            className="pl-9"
          />
        </div>
        <Button type="submit" variant="secondary">Search</Button>
      </form>

      <DataTable
        columns={userColumns}
        data={data?.data ?? []}
        loading={isLoading}
        page={params.page}
        totalPages={data?.pagination?.totalPages ?? 1}
        total={data?.pagination?.total ?? 0}
        sort={params.sort}
        order={params.order}
        onPageChange={setPage}
        onSort={setSort}
      />
    </div>
  )
}
