'use client'

import { useState } from 'react'
import Link from 'next/link'
import type { Route } from 'next'
import { useSession } from 'next-auth/react'
import { useRouter } from 'next/navigation'
import { trpc } from '@/lib/trpc/client'
import { directSessionUpdate } from '@/lib/session-update'
import { Button } from '@/components/ui/button'
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuCheckboxItem,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog'
import { toast } from 'sonner'
import {
  MoreHorizontal,
  Mail,
  UserCog,
  Trash2,
  Loader2,
  Shield,
  LogIn,
} from 'lucide-react'

type Role = 'SUPER_ADMIN' | 'PROGRAM_ADMIN' | 'JURY_MEMBER' | 'MENTOR' | 'OBSERVER'

const ROLE_LABELS: Record<Role, string> = {
  SUPER_ADMIN: 'Super Admin',
  PROGRAM_ADMIN: 'Program Admin',
  JURY_MEMBER: 'Jury Member',
  MENTOR: 'Mentor',
  OBSERVER: 'Observer',
}

interface UserActionsProps {
  userId: string
  userEmail: string
  userStatus: string
  userRole: Role
  userRoles?: Role[]
  currentUserRole?: Role
}

function getRoleHomePath(role: string): string {
  switch (role) {
    case 'JURY_MEMBER': return '/jury'
    case 'APPLICANT': return '/applicant'
    case 'MENTOR': return '/mentor'
    case 'OBSERVER': return '/observer'
    default: return '/admin'
  }
}

export function UserActions({ userId, userEmail, userStatus, userRole, userRoles, currentUserRole }: UserActionsProps) {
  const [showDeleteDialog, setShowDeleteDialog] = useState(false)
  const [isSending, setIsSending] = useState(false)
  const { data: session } = useSession()
  const router = useRouter()

  const utils = trpc.useUtils()
  const sendInvitation = trpc.user.sendInvitation.useMutation()
  const deleteUser = trpc.user.delete.useMutation({
    onSuccess: () => {
      utils.user.list.invalidate()
    },
  })
  const startImpersonation = trpc.user.startImpersonation.useMutation()
  const updateRoles = trpc.user.updateRoles.useMutation({
    onSuccess: () => {
      utils.user.list.invalidate()
      toast.success('Roles updated successfully')
    },
    onError: (error) => {
      toast.error(error.message || 'Failed to update roles')
    },
  })

  const isSuperAdmin = currentUserRole === 'SUPER_ADMIN'

  // Determine which roles can be assigned
  const getAvailableRoles = (): Role[] => {
    if (isSuperAdmin) {
      return ['SUPER_ADMIN', 'PROGRAM_ADMIN', 'JURY_MEMBER', 'MENTOR', 'OBSERVER']
    }
    // Program admins can only assign lower roles
    return ['JURY_MEMBER', 'MENTOR', 'OBSERVER']
  }

  // Can this user's role be changed by the current user?
  const canChangeRole = isSuperAdmin || (!['SUPER_ADMIN', 'PROGRAM_ADMIN'].includes(userRole))

  // Current roles for this user (array or fallback to single role)
  const currentRoles: Role[] = userRoles?.length ? userRoles : [userRole]

  const handleToggleRole = (role: Role) => {
    const has = currentRoles.includes(role)
    let newRoles: Role[]
    if (has) {
      // Don't allow removing the last role
      if (currentRoles.length <= 1) return
      newRoles = currentRoles.filter(r => r !== role)
    } else {
      newRoles = [...currentRoles, role]
    }
    updateRoles.mutate({ userId, roles: newRoles })
  }

  const handleImpersonate = async () => {
    try {
      const result = await startImpersonation.mutateAsync({ targetUserId: userId })
      // Direct POST to session endpoint — bypasses useSession().update()'s loading gate
      const ok = await directSessionUpdate({ impersonate: userId })
      if (!ok) {
        toast.error('Failed to update session for impersonation')
        return
      }
      window.location.href = getRoleHomePath(result.targetRole)
    } catch (error) {
      toast.error(error instanceof Error ? error.message : 'Failed to start impersonation')
    }
  }

  const handleSendInvitation = async () => {
    if (userStatus !== 'NONE' && userStatus !== 'INVITED') {
      toast.error('User has already accepted their invitation')
      return
    }

    setIsSending(true)
    try {
      await sendInvitation.mutateAsync({ userId })
      toast.success(`Invitation sent to ${userEmail}`)
      // Invalidate in case status changed
      utils.user.list.invalidate()
    } catch (error) {
      toast.error(error instanceof Error ? error.message : 'Failed to send invitation')
    } finally {
      setIsSending(false)
    }
  }

  const handleDelete = async () => {
    try {
      await deleteUser.mutateAsync({ id: userId })
      toast.success('User deleted successfully')
      setShowDeleteDialog(false)
    } catch (error) {
      toast.error(error instanceof Error ? error.message : 'Failed to delete user')
    }
  }

  return (
    <>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button variant="ghost" size="icon">
            {isSending ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <MoreHorizontal className="h-4 w-4" />
            )}
            <span className="sr-only">Actions</span>
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          <DropdownMenuItem asChild>
            <Link href={`/admin/members/${userId}`}>
              <UserCog className="mr-2 h-4 w-4" />
              Edit
            </Link>
          </DropdownMenuItem>
          {isSuperAdmin && session?.user?.id !== userId && (
            <DropdownMenuItem
              onClick={handleImpersonate}
              disabled={startImpersonation.isPending}
            >
              {startImpersonation.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : (
                <LogIn className="mr-2 h-4 w-4" />
              )}
              Login As
            </DropdownMenuItem>
          )}
          {canChangeRole && (
            <DropdownMenuSub>
              <DropdownMenuSubTrigger disabled={updateRoles.isPending}>
                <Shield className="mr-2 h-4 w-4" />
                {updateRoles.isPending ? 'Updating...' : 'Roles'}
              </DropdownMenuSubTrigger>
              <DropdownMenuSubContent>
                {getAvailableRoles().map((role) => (
                  <DropdownMenuCheckboxItem
                    key={role}
                    checked={currentRoles.includes(role)}
                    onCheckedChange={() => handleToggleRole(role)}
                    disabled={currentRoles.includes(role) && currentRoles.length <= 1}
                  >
                    {ROLE_LABELS[role]}
                  </DropdownMenuCheckboxItem>
                ))}
              </DropdownMenuSubContent>
            </DropdownMenuSub>
          )}
          <DropdownMenuItem
            onClick={handleSendInvitation}
            disabled={(userStatus !== 'NONE' && userStatus !== 'INVITED') || isSending}
          >
            <Mail className="mr-2 h-4 w-4" />
            {isSending ? 'Sending...' : 'Send Invite'}
          </DropdownMenuItem>
          <DropdownMenuSeparator />
          <DropdownMenuItem
            className="text-destructive focus:text-destructive"
            onClick={() => setShowDeleteDialog(true)}
          >
            <Trash2 className="mr-2 h-4 w-4" />
            Remove
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>

      <AlertDialog open={showDeleteDialog} onOpenChange={setShowDeleteDialog}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete User</AlertDialogTitle>
            <AlertDialogDescription>
              Are you sure you want to delete {userEmail}? This action cannot be
              undone and will remove all their assignments and evaluations.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction
              onClick={handleDelete}
              className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
            >
              {deleteUser.isPending ? (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              ) : null}
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  )
}

interface UserMobileActionsProps {
  userId: string
  userEmail: string
  userStatus: string
  userRole: Role
  userRoles?: Role[]
  currentUserRole?: Role
}

export function UserMobileActions({
  userId,
  userEmail,
  userStatus,
  userRole,
  userRoles,
  currentUserRole,
}: UserMobileActionsProps) {
  const [isSending, setIsSending] = useState(false)
  const { data: session } = useSession()
  const router = useRouter()
  const utils = trpc.useUtils()
  const sendInvitation = trpc.user.sendInvitation.useMutation()
  const startImpersonation = trpc.user.startImpersonation.useMutation()
  const updateRoles = trpc.user.updateRoles.useMutation({
    onSuccess: () => {
      utils.user.list.invalidate()
      toast.success('Roles updated successfully')
    },
    onError: (error) => {
      toast.error(error.message || 'Failed to update roles')
    },
  })

  const isSuperAdmin = currentUserRole === 'SUPER_ADMIN'
  const canChangeRole = isSuperAdmin || (!['SUPER_ADMIN', 'PROGRAM_ADMIN'].includes(userRole))
  const currentRoles: Role[] = userRoles?.length ? userRoles : [userRole]

  const handleImpersonateMobile = async () => {
    try {
      const result = await startImpersonation.mutateAsync({ targetUserId: userId })
      const ok = await directSessionUpdate({ impersonate: userId })
      if (!ok) {
        toast.error('Failed to update session for impersonation')
        return
      }
      window.location.href = getRoleHomePath(result.targetRole)
    } catch (error) {
      toast.error(error instanceof Error ? error.message : 'Failed to start impersonation')
    }
  }

  const handleSendInvitation = async () => {
    if (userStatus !== 'NONE' && userStatus !== 'INVITED') {
      toast.error('User has already accepted their invitation')
      return
    }

    setIsSending(true)
    try {
      await sendInvitation.mutateAsync({ userId })
      toast.success(`Invitation sent to ${userEmail}`)
      utils.user.list.invalidate()
    } catch (error) {
      toast.error(error instanceof Error ? error.message : 'Failed to send invitation')
    } finally {
      setIsSending(false)
    }
  }

  return (
    <div className="space-y-2 pt-2">
      <div className="flex gap-2">
        <Button variant="outline" size="sm" className="flex-1" asChild>
          <Link href={`/admin/members/${userId}`}>
            <UserCog className="mr-2 h-4 w-4" />
            Edit
          </Link>
        </Button>
        {isSuperAdmin && session?.user?.id !== userId && (
          <Button
            variant="outline"
            size="sm"
            className="flex-1"
            onClick={handleImpersonateMobile}
            disabled={startImpersonation.isPending}
          >
            {startImpersonation.isPending ? (
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
            ) : (
              <LogIn className="mr-2 h-4 w-4" />
            )}
            Login As
          </Button>
        )}
        <Button
          variant="outline"
          size="sm"
          className="flex-1"
          onClick={handleSendInvitation}
          disabled={(userStatus !== 'NONE' && userStatus !== 'INVITED') || isSending}
        >
          {isSending ? (
            <Loader2 className="mr-2 h-4 w-4 animate-spin" />
          ) : (
            <Mail className="mr-2 h-4 w-4" />
          )}
          Invite
        </Button>
      </div>
      {canChangeRole && (
        <div className="flex flex-wrap gap-1.5">
          {(isSuperAdmin
            ? (['SUPER_ADMIN', 'PROGRAM_ADMIN', 'JURY_MEMBER', 'MENTOR', 'OBSERVER'] as Role[])
            : (['JURY_MEMBER', 'MENTOR', 'OBSERVER'] as Role[])
          ).map((role) => {
            const isActive = currentRoles.includes(role)
            return (
              <Button
                key={role}
                variant={isActive ? 'default' : 'outline'}
                size="sm"
                className="h-6 text-xs px-2"
                disabled={updateRoles.isPending || (isActive && currentRoles.length <= 1)}
                onClick={() => {
                  const newRoles = isActive
                    ? currentRoles.filter(r => r !== role)
                    : [...currentRoles, role]
                  updateRoles.mutate({ userId, roles: newRoles })
                }}
              >
                {ROLE_LABELS[role]}
              </Button>
            )
          })}
        </div>
      )}
    </div>
  )
}
