"use client"

import { useCallback, useEffect, useState } from "react"
import { PageHeader } from "@/components/page-header"
import { DataPageCard } from "@/components/data-page-card"
import { UsersDataGrid } from "@/components/data-grids/users-data-grid"
import { KpiStatGrid } from "@/components/reui-kit/kpi-stat-grid"
import { UserSheet } from "@/components/users/user-sheet"
import { Button } from "@/components/ui/button"
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogMedia,
  AlertDialogTitle,
} from "@/components/ui/alert-dialog"
import { servers as mockServers } from "@/lib/data"
import { useDataSource } from "@/lib/data-source"
import {
  ALL_SECTIONS,
  INIT_USERS,
  bindingDiffKey,
  userInitials,
  type AppUser,
  type AppUserForm,
  type UserServerOption,
} from "@/lib/users"
import { listServers } from "@/shared/api/servers"
import {
  createAppUser,
  createUserBinding,
  deleteAppUser,
  deleteUserBinding,
  listAppUsers,
  updateAppUser,
} from "@/shared/api/users"
import { ApiClientError } from "@/shared/api/http-client"
import { toast } from "sonner"
import {
  CableIcon,
  PlusIcon,
  TrashIcon,
  UserCheckIcon,
  UsersIcon,
} from "lucide-react"

function toServerOptionsFromMock(): UserServerOption[] {
  return mockServers.map((s) => ({
    id: s.id,
    name: s.name,
    host: s.host,
    site: s.site,
    country: s.country,
    status: s.status,
  }))
}

export default function UsersPage() {
  const { mode, backendUrl } = useDataSource()
  const isLive = mode === "live"

  const [users, setUsers] = useState<AppUser[]>(INIT_USERS)
  const [serverOptions, setServerOptions] = useState<UserServerOption[]>(toServerOptionsFromMock)
  const [loading, setLoading] = useState(false)
  const [saving, setSaving] = useState(false)
  const [sheetOpen, setSheetOpen] = useState(false)
  const [editUser, setEditUser] = useState<AppUser | null>(null)
  const [deleteTarget, setDeleteTarget] = useState<AppUser | null>(null)

  const loadLive = useCallback(async () => {
    setLoading(true)
    try {
      const [list, srvs] = await Promise.all([
        listAppUsers(backendUrl),
        listServers(backendUrl),
      ])
      setUsers(list)
      setServerOptions(srvs.map((s) => ({
        id: String(s.id),
        name: s.name || s.host,
        host: s.host,
        site: s.site,
        country: s.country,
        status: s.status,
      })))
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Не удалось загрузить пользователей")
    } finally {
      setLoading(false)
    }
  }, [backendUrl])

  useEffect(() => {
    if (!isLive) {
      setUsers(INIT_USERS)
      setServerOptions(toServerOptionsFromMock())
      return
    }
    void loadLive()
  }, [isLive, loadLive])

  const boundCount = users.reduce((n, u) => n + u.bindings.length, 0)
  const activeCount = users.filter((u) => u.active).length

  const applyBindingsDiff = async (userId: string, next: AppUserForm["bindings"], prev: AppUser["bindings"]) => {
    const nextKeys = new Set(next.map(bindingDiffKey))
    const prevKeys = new Map(prev.map((b) => [bindingDiffKey(b), b] as const))
    for (const b of prev) {
      if (!nextKeys.has(bindingDiffKey(b))) {
        await deleteUserBinding(backendUrl, userId, b.id)
      }
    }
    for (const b of next) {
      if (!prevKeys.has(bindingDiffKey(b))) {
        await createUserBinding(backendUrl, userId, {
          serverId: Number(b.serverId),
          interfaceName: b.interfaceName,
          interfaceType: b.interfaceType,
          peerPublicKey: b.peerPublicKey,
          peerName: b.peerName,
          comment: b.comment,
        })
      }
    }
  }

  const handleSave = async (form: AppUserForm) => {
    if (!isLive) {
      if (!editUser) {
        const id = `u${Date.now()}`
        const created: AppUser = {
          id,
          ...form,
          last: "только что",
          avatar: userInitials(form.name),
          bindings: form.bindings.map((b, i) => ({ ...b, id: `b${id}-${i}`, userId: id })),
        }
        setUsers((prev) => [...prev, created])
      } else {
        setUsers((prev) => prev.map((u) => u.id === editUser.id ? { ...u, ...form, avatar: userInitials(form.name) } : u))
      }
      setSheetOpen(false)
      toast.success(editUser ? "Пользователь сохранён" : "Пользователь создан")
      return
    }

    setSaving(true)
    try {
      if (!editUser) {
        const created = await createAppUser(backendUrl, {
          name: form.name,
          login: form.login,
          email: form.email,
          role: form.role,
          active: form.active,
          avatar: userInitials(form.name),
          sections: form.sections,
          servers: form.servers,
        })
        await applyBindingsDiff(created.id, form.bindings, [])
        await loadLive()
      } else {
        await updateAppUser(backendUrl, editUser.id, {
          name: form.name,
          login: form.login,
          email: form.email,
          role: form.role,
          active: form.active,
          avatar: userInitials(form.name),
          sections: form.sections,
          servers: form.servers,
        })
        await applyBindingsDiff(editUser.id, form.bindings, editUser.bindings)
        await loadLive()
      }
      setSheetOpen(false)
      toast.success(editUser ? "Пользователь сохранён" : "Пользователь создан")
    } catch (err) {
      const msg = err instanceof ApiClientError ? err.message : err instanceof Error ? err.message : "Ошибка сохранения"
      toast.error(msg)
    } finally {
      setSaving(false)
    }
  }

  const handleDelete = async () => {
    if (!deleteTarget) return
    if (!isLive) {
      setUsers((prev) => prev.filter((u) => u.id !== deleteTarget.id))
      setDeleteTarget(null)
      toast.success("Пользователь удалён")
      return
    }
    try {
      await deleteAppUser(backendUrl, deleteTarget.id)
      setDeleteTarget(null)
      await loadLive()
      toast.success("Пользователь удалён")
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Не удалось удалить")
    }
  }

  return (
    <div className="flex flex-col h-full">
      <PageHeader
        crumbs={[{ label: "Управление" }, { label: "Пользователи" }]}
        actions={
          <Button size="sm" onClick={() => { setEditUser(null); setSheetOpen(true) }}>
            <PlusIcon className="size-4" />Пригласить
          </Button>
        }
      />

      <div className="flex-1 overflow-y-auto p-6 flex flex-col gap-5">
        {/* Preview: https://reui.io/preview/base/stats-12 · https://reui.io/docs/components/base/icon-tile */}
        <KpiStatGrid
          aria-label="Сводка пользователей"
          items={[
            {
              id: "all",
              label: "Пользователи",
              value: users.length,
              icon: <UsersIcon className="size-4" />,
              iconClassName: "text-muted-foreground",
            },
            {
              id: "active",
              label: "Активные",
              value: activeCount,
              icon: <UserCheckIcon className="size-4" />,
              iconClassName: "text-success",
            },
            {
              id: "ifaces",
              label: "Привязанные ifaces",
              value: boundCount,
              icon: <CableIcon className="size-4" />,
              iconClassName: "text-info",
            },
          ]}
        />

        {/* Preview: https://reui.io/preview/base/data-grid-filtering-2 · https://reui.io/docs/components/base/data-grid · https://reui.io/docs/components/base/frame */}
        <DataPageCard>
          <UsersDataGrid
            users={users}
            serversCount={serverOptions.length}
            allSectionsCount={ALL_SECTIONS.length}
            isLoading={loading}
            onEdit={(u) => { setEditUser(u); setSheetOpen(true) }}
            onDelete={setDeleteTarget}
          />
        </DataPageCard>
      </div>

      <UserSheet
        key={sheetOpen ? (editUser?.id ?? "create") : "closed"}
        open={sheetOpen}
        user={editUser}
        users={users}
        servers={serverOptions}
        isLive={isLive}
        backendUrl={backendUrl}
        saving={saving}
        onSave={(f) => { void handleSave(f) }}
        onClose={() => setSheetOpen(false)}
      />

      {deleteTarget && (
        <AlertDialog open={!!deleteTarget} onOpenChange={(v) => { if (!v) setDeleteTarget(null) }}>
          <AlertDialogContent size="default">
            <AlertDialogHeader>
              <AlertDialogMedia className="bg-destructive/10 text-destructive">
                <TrashIcon />
              </AlertDialogMedia>
              <AlertDialogTitle>Удалить пользователя?</AlertDialogTitle>
              <AlertDialogDescription>
                {deleteTarget.name} · {deleteTarget.email || deleteTarget.login}. Привязки интерфейсов будут удалены.
              </AlertDialogDescription>
            </AlertDialogHeader>
            <AlertDialogFooter>
              <AlertDialogCancel onClick={() => setDeleteTarget(null)}>Отмена</AlertDialogCancel>
              <AlertDialogAction variant="destructive" onClick={() => { void handleDelete() }}>
                Удалить
              </AlertDialogAction>
            </AlertDialogFooter>
          </AlertDialogContent>
        </AlertDialog>
      )}
    </div>
  )
}
