"use client"

import { useEffect, useMemo, useState } from "react"
import { MoreHorizontal, UserPlus } from "lucide-react"
import { SettingsSectionHeader } from "@/components/gmail/settings/settings-section-header"
import { SettingsSyncBanner } from "@/components/gmail/settings/settings-sync-banner"
import { useAdminUser, useAdminUsers } from "@/lib/api/hooks/use-admin-queries"
import {
  useDeleteAdminUser,
  useDisableAdminUser,
  useInviteAdminUser,
  useReactivateAdminUser,
  useSetAdminUserQuota,
  useSetAdminUserRole,
  useUpdateAdminUser,
} from "@/lib/api/hooks/use-admin-mutations"
import type { AdminUser, AdminUserRole } from "@/lib/api/admin-types"
import { bytesToGib, formatBytes, gibToBytes } from "@/lib/admin/format-bytes"
import {
  resolveUserRole,
  USER_ROLE_DESCRIPTIONS,
  USER_ROLE_FILTER_ALL_ICON,
  USER_ROLE_ICONS,
  USER_ROLE_LABELS,
} from "@/lib/admin/user-role"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Badge } from "@/components/ui/badge"
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import {
  Sheet,
  SheetContent,
  SheetHeader,
  SheetTitle,
} from "@/components/ui/sheet"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

const ROLE_OPTIONS: AdminUserRole[] = ["admin", "user", "guest", "suspended"]

export function UsersSection() {
  const [q, setQ] = useState("")
  const [role, setRole] = useState<string>("all")
  const [page, setPage] = useState(1)
  const [inviteOpen, setInviteOpen] = useState(false)
  const [selectedId, setSelectedId] = useState<string | null>(null)

  const queryParams = useMemo(
    () => ({
      page,
      page_size: 25,
      q: q.trim() || undefined,
      role: role === "all" ? undefined : role,
    }),
    [page, q, role]
  )

  const { data, isFetching, isError, refetch } = useAdminUsers(queryParams)
  const users = data?.users ?? []
  const total = data?.pagination.total ?? 0
  const pageSize = data?.pagination.page_size ?? 25
  const totalPages = Math.max(1, Math.ceil(total / pageSize))

  return (
    <>
      <SettingsSectionHeader
        title="Utilisateurs"
        description="Comptes, types d'utilisateur, invitations et quotas."
      />
      <SettingsSyncBanner isFetching={isFetching} isError={isError} onRetry={() => refetch()} />

      <div className="mb-4 flex flex-wrap items-end gap-3">
        <div className="min-w-[200px] flex-1">
          <Label className="text-xs">Recherche</Label>
          <Input
            className="mt-1 h-9"
            value={q}
            onChange={(e) => {
              setQ(e.target.value)
              setPage(1)
            }}
            placeholder="E-mail, nom ou ID externe"
          />
        </div>
        <div className="w-52">
          <Label className="text-xs">Type d&apos;utilisateur</Label>
          <Select
            value={role}
            onValueChange={(v) => {
              setRole(v)
              setPage(1)
            }}
          >
            <SelectTrigger className="mt-1 h-9">
              <SelectValue>
                {role === "all" ? (
                  <UserRoleLabel role="all" />
                ) : (
                  <UserRoleLabel role={role as AdminUserRole} />
                )}
              </SelectValue>
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">
                <UserRoleLabel role="all" />
              </SelectItem>
              {ROLE_OPTIONS.map((option) => (
                <SelectItem key={option} value={option}>
                  <UserRoleLabel role={option} />
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <Button className="h-9" onClick={() => setInviteOpen(true)}>
          <UserPlus className="mr-2 size-4" />
          Inviter
        </Button>
      </div>

      <div className="overflow-x-auto rounded-lg border">
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>Utilisateur</TableHead>
              <TableHead>Type</TableHead>
              <TableHead className="hidden lg:table-cell">Mail</TableHead>
              <TableHead className="hidden lg:table-cell">Drive</TableHead>
              <TableHead className="hidden md:table-cell">ID externe</TableHead>
              <TableHead className="w-12" />
            </TableRow>
          </TableHeader>
          <TableBody>
            {users.length === 0 ? (
              <TableRow>
                <TableCell colSpan={6} className="text-center text-muted-foreground">
                  Aucun utilisateur trouvé.
                </TableCell>
              </TableRow>
            ) : (
              users.map((user) => (
                <UserRow
                  key={user.id}
                  user={user}
                  onOpen={() => setSelectedId(user.id)}
                />
              ))
            )}
          </TableBody>
        </Table>
      </div>

      {totalPages > 1 ? (
        <div className="mt-4 flex items-center justify-between text-sm">
          <span className="text-muted-foreground">
            {total.toLocaleString("fr-FR")} utilisateur(s)
          </span>
          <div className="flex gap-2">
            <Button
              variant="outline"
              size="sm"
              disabled={page <= 1}
              onClick={() => setPage((p) => p - 1)}
            >
              Précédent
            </Button>
            <Button
              variant="outline"
              size="sm"
              disabled={page >= totalPages}
              onClick={() => setPage((p) => p + 1)}
            >
              Suivant
            </Button>
          </div>
        </div>
      ) : null}

      <InviteUserDialog open={inviteOpen} onOpenChange={setInviteOpen} />
      <UserDetailSheet userId={selectedId} onClose={() => setSelectedId(null)} />
    </>
  )
}

function UserRow({ user, onOpen }: { user: AdminUser; onOpen: () => void }) {
  const disableUser = useDisableAdminUser()
  const reactivateUser = useReactivateAdminUser()
  const deleteUser = useDeleteAdminUser()

  return (
    <TableRow className="cursor-pointer" onClick={onOpen}>
      <TableCell>
        <div className="font-medium">{user.name || "—"}</div>
        <div className="text-xs text-muted-foreground">{user.email}</div>
      </TableCell>
      <TableCell>
        <RoleBadge role={resolveUserRole(user)} />
      </TableCell>
      <TableCell className="hidden text-xs text-muted-foreground lg:table-cell">
        {formatBytes(user.storage?.mail_used_bytes ?? 0)}
      </TableCell>
      <TableCell className="hidden text-xs text-muted-foreground lg:table-cell">
        {formatBytes(user.storage?.drive_used_bytes ?? 0)}
      </TableCell>
      <TableCell className="hidden max-w-[200px] truncate font-mono text-xs md:table-cell">
        {user.external_id}
      </TableCell>
      <TableCell onClick={(e) => e.stopPropagation()}>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button variant="ghost" size="icon" className="size-8">
              <MoreHorizontal className="size-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end">
            <DropdownMenuItem onClick={onOpen}>Détails et quotas</DropdownMenuItem>
            {resolveUserRole(user) !== "suspended" ? (
              <DropdownMenuItem
                onClick={() => void disableUser.mutateAsync(user.id)}
              >
                Suspendre
              </DropdownMenuItem>
            ) : (
              <DropdownMenuItem
                onClick={() => void reactivateUser.mutateAsync(user.id)}
              >
                Réactiver
              </DropdownMenuItem>
            )}
            <DropdownMenuSeparator />
            <DropdownMenuItem
              className="text-destructive"
              onClick={() => {
                if (confirm(`Supprimer définitivement ${user.email} ?`)) {
                  void deleteUser.mutateAsync(user.id)
                }
              }}
            >
              Supprimer
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </TableCell>
    </TableRow>
  )
}

function UserRoleLabel({
  role,
  className,
}: {
  role: AdminUserRole | "all"
  className?: string
}) {
  const Icon =
    role === "all" ? USER_ROLE_FILTER_ALL_ICON : USER_ROLE_ICONS[role]
  const label = role === "all" ? "Tous les types" : USER_ROLE_LABELS[role]

  return (
    <span className={cn("flex items-center gap-2", className)}>
      <Icon className="size-4 shrink-0 opacity-80" aria-hidden />
      <span>{label}</span>
    </span>
  )
}

function RoleBadge({ role }: { role: AdminUserRole }) {
  const variant =
    role === "admin"
      ? "default"
      : role === "user"
        ? "secondary"
        : role === "guest"
          ? "outline"
          : "destructive"
  const Icon = USER_ROLE_ICONS[role]
  return (
    <Badge variant={variant} className="gap-1.5 pr-2.5">
      <Icon className="size-3.5" aria-hidden />
      {USER_ROLE_LABELS[role] ?? role}
    </Badge>
  )
}

function InviteUserDialog({
  open,
  onOpenChange,
}: {
  open: boolean
  onOpenChange: (open: boolean) => void
}) {
  const invite = useInviteAdminUser()
  const [email, setEmail] = useState("")
  const [name, setName] = useState("")

  async function submit() {
    await invite.mutateAsync({ email, name: name || undefined })
    setEmail("")
    setName("")
    onOpenChange(false)
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Inviter un utilisateur</DialogTitle>
        </DialogHeader>
        <div className="space-y-3">
          <div>
            <Label>E-mail</Label>
            <Input
              className="mt-1"
              type="email"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
            />
          </div>
          <div>
            <Label>Nom (optionnel)</Label>
            <Input
              className="mt-1"
              value={name}
              onChange={(e) => setName(e.target.value)}
            />
          </div>
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Annuler
          </Button>
          <Button disabled={!email || invite.isPending} onClick={() => void submit()}>
            Envoyer l&apos;invitation
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}

function UserDetailSheet({
  userId,
  onClose,
}: {
  userId: string | null
  onClose: () => void
}) {
  const { data: user, isFetching } = useAdminUser(userId)
  const updateUser = useUpdateAdminUser(userId ?? "")
  const setRole = useSetAdminUserRole(userId ?? "")
  const setQuota = useSetAdminUserQuota(userId ?? "")
  const [name, setName] = useState("")
  const [email, setEmail] = useState("")
  const [selectedRole, setSelectedRole] = useState<AdminUserRole>("user")
  const [mailGib, setMailGib] = useState("5")
  const [driveGib, setDriveGib] = useState("5")
  const [photosGib, setPhotosGib] = useState("5")

  const open = Boolean(userId)

  useEffect(() => {
    if (!user) return
    setName(user.name ?? "")
    setEmail(user.email ?? "")
    setSelectedRole(resolveUserRole(user))
    if (user.quota) {
      setMailGib(String(bytesToGib(user.quota.mail.max_storage_bytes).toFixed(1)))
      setDriveGib(String(bytesToGib(user.quota.drive.max_storage_bytes).toFixed(1)))
      setPhotosGib(String(bytesToGib(user.quota.photos.max_storage_bytes).toFixed(1)))
    }
  }, [user])

  async function saveProfile() {
    if (!userId) return
    await updateUser.mutateAsync({ name, email })
  }

  async function saveRole() {
    if (!userId || !user || selectedRole === resolveUserRole(user)) return
    await setRole.mutateAsync({ role: selectedRole })
  }

  async function saveQuotas() {
    if (!userId) return
    await setQuota.mutateAsync({
      mail_max_storage_bytes: gibToBytes(Number(mailGib)),
      drive_max_storage_bytes: gibToBytes(Number(driveGib)),
      photos_max_storage_bytes: gibToBytes(Number(photosGib)),
    })
  }

  return (
    <Sheet open={open} onOpenChange={(v) => !v && onClose()}>
      <SheetContent className="flex flex-col gap-0 overflow-y-auto p-0 sm:max-w-lg">
        <SheetHeader className="border-b px-6 py-5">
          <SheetTitle>Détails utilisateur</SheetTitle>
        </SheetHeader>

        {isFetching || !user ? (
          <p className="px-6 py-5 text-sm text-muted-foreground">Chargement…</p>
        ) : (
          <div className="space-y-8 px-6 py-6">
            <div className="space-y-4">
              <RoleBadge role={resolveUserRole(user)} />
              <div className="space-y-2">
                <Label>Type d&apos;utilisateur</Label>
                <Select
                  value={selectedRole}
                  onValueChange={(v) => setSelectedRole(v as AdminUserRole)}
                >
                  <SelectTrigger>
                    <SelectValue>
                      <UserRoleLabel role={selectedRole} />
                    </SelectValue>
                  </SelectTrigger>
                  <SelectContent>
                    {ROLE_OPTIONS.map((option) => (
                      <SelectItem key={option} value={option}>
                        <UserRoleLabel role={option} />
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
                <p className="text-xs text-muted-foreground">
                  {USER_ROLE_DESCRIPTIONS[selectedRole]}
                </p>
                <Button
                  size="sm"
                  variant="secondary"
                  onClick={() => void saveRole()}
                  disabled={setRole.isPending || selectedRole === resolveUserRole(user)}
                >
                  Enregistrer le type
                </Button>
              </div>
              <div className="space-y-2">
                <Label>Nom</Label>
                <Input value={name} onChange={(e) => setName(e.target.value)} />
              </div>
              <div className="space-y-2">
                <Label>E-mail</Label>
                <Input value={email} onChange={(e) => setEmail(e.target.value)} />
              </div>
              <Button size="sm" onClick={() => void saveProfile()} disabled={updateUser.isPending}>
                Mettre à jour le profil
              </Button>
            </div>

            {user.quota ? (
              <div className="space-y-5 rounded-lg border bg-muted/20 p-5">
                <h3 className="text-sm font-medium">Quotas stockage</h3>
                <QuotaField
                  label="Mail"
                  used={coerceBytes(user.quota.mail.used_storage_bytes)}
                  max={coerceBytes(user.quota.mail.max_storage_bytes)}
                  gib={mailGib}
                  onGibChange={setMailGib}
                  count={user.quota.mail.count}
                />
                <QuotaField
                  label="Drive"
                  used={coerceBytes(user.quota.drive.used_storage_bytes)}
                  max={coerceBytes(user.quota.drive.max_storage_bytes)}
                  gib={driveGib}
                  onGibChange={setDriveGib}
                />
                <QuotaField
                  label="Photos"
                  used={coerceBytes(user.quota.photos.used_storage_bytes)}
                  max={coerceBytes(user.quota.photos.max_storage_bytes)}
                  gib={photosGib}
                  onGibChange={setPhotosGib}
                />
                <Button size="sm" onClick={() => void saveQuotas()} disabled={setQuota.isPending}>
                  Enregistrer les quotas
                </Button>
              </div>
            ) : null}

            <p className="font-mono text-xs text-muted-foreground">ID : {user.id}</p>
          </div>
        )}
      </SheetContent>
    </Sheet>
  )
}

function coerceBytes(value: unknown): number {
  const n = typeof value === "number" ? value : Number(value)
  return Number.isFinite(n) && n >= 0 ? n : 0
}

function QuotaField({
  label,
  used,
  max,
  gib,
  onGibChange,
  count,
}: {
  label: string
  used: number
  max: number
  gib: string
  onGibChange: (v: string) => void
  count?: number
}) {
  const maxBytes = max > 0 ? max : gibToBytes(Number(gib) || 0)
  const pct = maxBytes > 0 ? Math.min(100, Math.round((used / maxBytes) * 100)) : 0

  return (
    <div className="space-y-2">
      <div className="flex items-center justify-between gap-3 text-xs">
        <span className="font-medium text-foreground">{label}</span>
        <span className="text-right text-muted-foreground">
          {formatBytes(used)} / {formatBytes(maxBytes)}
          {count !== undefined ? ` · ${count} messages` : ""}
        </span>
      </div>
      <div className="h-1.5 overflow-hidden rounded-full bg-muted">
        <div
          className="h-full rounded-full bg-primary transition-all"
          style={{ width: `${pct}%` }}
        />
      </div>
      <div className="flex items-center gap-2">
        <Label className="sr-only">Quota {label}</Label>
        <Input
          type="number"
          min={0}
          step={0.5}
          className="h-9"
          value={gib}
          onChange={(e) => onGibChange(e.target.value)}
        />
        <span className="shrink-0 text-sm text-muted-foreground">Go max</span>
      </div>
    </div>
  )
}
