"use client"

import * as React from "react"
import { useState, useEffect } from "react"
import { useTranslation } from "react-i18next"
import { RiAddLine, RiDeleteBin5Line, RiEdit2Line, RiGroup2Fill } from "@remixicon/react"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { SearchInput } from "@/components/search-input"
import { Page } from "@/components/page"
import { PageHeader } from "@/components/page-header"
import { DataTable } from "@/components/data-table/data-table"
import { DataTablePagination } from "@/components/data-table/data-table-pagination"
import { useDataTable } from "@/hooks/use-data-table"
import { usePermissions } from "@/hooks/use-permissions"
import { UserNewForm } from "@/components/user/new-form"
import { UserEditForm } from "@/components/user/edit-form"
import { UserAddToGroupForm } from "@/components/user/add-to-group-form"
import { useUsers } from "@/hooks/use-users"
import { useDialog } from "@/lib/feedback/dialog"
import { useMessage } from "@/lib/feedback/message"
import { formatDateTime } from "@/lib/functions"
import type { ColumnDef } from "@tanstack/react-table"

interface UserRow {
  accessKey: string
  policyName?: string
  status: string
  memberOf?: string[]
  updatedAt?: string
  [key: string]: unknown
}

function formatDate(dateStr?: string) {
  if (!dateStr) return "-"
  const parsedDate = new Date(dateStr)
  if (!Number.isNaN(parsedDate.getTime())) return formatDateTime(parsedDate)
  const [datePart, timeRaw, offsetRaw] = (dateStr || "").split(" ")
  if (datePart && timeRaw && offsetRaw) {
    const time = timeRaw.substring(0, 12)
    const offset = offsetRaw.substring(0, 6)
    const isoStr = `${datePart}T${time}${offset}`
    const normalizedDate = new Date(isoStr)
    if (!Number.isNaN(normalizedDate.getTime())) return formatDateTime(normalizedDate)
  }
  return "-"
}

export default function UsersPage() {
  const { t } = useTranslation()
  const message = useMessage()
  const dialog = useDialog()
  const { listUsers, deleteUser } = useUsers()
  const { canCapability } = usePermissions()

  const canCreateUser = canCapability("users.create")
  const canEditUser =
    canCapability("users.edit") || canCapability("users.assignGroups") || canCapability("users.policy.edit")
  const canDeleteUser = canCapability("users.delete")
  const canBulkDeleteUsers = canCapability("users.bulkDelete")
  const canAssignGroups = canCapability("users.assignGroups")

  const [data, setData] = useState<UserRow[]>([])
  const [loading, setLoading] = useState(false)
  const [searchTerm, setSearchTerm] = useState("")
  const [newFormOpen, setNewFormOpen] = useState(false)
  const [editFormOpen, setEditFormOpen] = useState(false)
  const [addToGroupOpen, setAddToGroupOpen] = useState(false)
  const [editRow, setEditRow] = useState<UserRow | null>(null)

  const getDataList = React.useCallback(async () => {
    setLoading(true)
    try {
      const res = (await listUsers()) as Record<string, Record<string, unknown>>
      const users: UserRow[] = Object.entries(res ?? {}).map(([username, info]) => ({
        accessKey: username,
        ...(typeof info === "object" ? info : {}),
      })) as UserRow[]
      setData(users)
    } catch {
      message.error(t("Failed to get data"))
    } finally {
      setLoading(false)
    }
  }, [listUsers, message, t])

  useEffect(() => {
    getDataList()
  }, [getDataList])

  const filteredData = React.useMemo(() => {
    if (!searchTerm) return data
    const term = searchTerm.toLowerCase()
    return data.filter((row) => row.accessKey.toLowerCase().includes(term))
  }, [data, searchTerm])

  const columns: ColumnDef<UserRow>[] = [
    {
      accessorKey: "accessKey",
      header: () => t("Name"),
      cell: ({ row }) => <span className="font-medium">{row.original.accessKey}</span>,
    },
    {
      accessorKey: "policyName",
      header: () => t("Policy Name"),
      cell: ({ row }) => <span>{row.original.policyName || ""}</span>,
    },
    {
      accessorKey: "status",
      header: () => t("Status"),
      cell: ({ row }) => (
        <Badge variant={row.original.status === "enabled" ? "secondary" : "outline"}>
          {row.original.status === "enabled" ? t("Enabled") : row.original.status}
        </Badge>
      ),
    },
    {
      accessorKey: "memberOf",
      header: () => t("Member Of"),
      cell: ({ row }) => <span>{row.original.memberOf?.join(", ") || ""}</span>,
    },
    {
      accessorKey: "updatedAt",
      header: () => t("Updated At"),
      cell: ({ row }) => <span>{formatDate(row.original.updatedAt)}</span>,
    },
    {
      id: "actions",
      header: () => t("Actions"),
      enableSorting: false,
      enableHiding: false,
      meta: { width: 200 },
      cell: ({ row }) => (
        <div className="flex items-center gap-2">
          {canEditUser ? (
            <Button type="button" variant="outline" size="sm" onClick={() => openEditItem(row.original)}>
              <RiEdit2Line className="size-4" aria-hidden />
              <span>{t("Edit")}</span>
            </Button>
          ) : null}
          {canDeleteUser ? (
            <Button type="button" variant="outline" size="sm" onClick={() => confirmDelete(row.original)}>
              <RiDeleteBin5Line className="size-4" aria-hidden />
              <span>{t("Delete")}</span>
            </Button>
          ) : null}
        </div>
      ),
    },
  ]

  const { table, selectedRowIds } = useDataTable<UserRow>({
    data: filteredData,
    columns,
    getRowId: (row) => row.accessKey,
    enableRowSelection: true,
    initialSorting: [{ id: "updatedAt", desc: true }],
  })

  const selectedKeys = selectedRowIds

  React.useEffect(() => {
    table.resetRowSelection()
  }, [data, table])

  const openEditItem = (row: UserRow) => {
    setEditRow(row)
    setEditFormOpen(true)
  }

  const confirmDelete = (row: UserRow) => {
    dialog.error({
      title: t("Warning"),
      content: t("Are you sure you want to delete this user?"),
      positiveText: t("Confirm"),
      negativeText: t("Cancel"),
      onPositiveClick: () => deleteItem(row),
    })
  }

  const deleteItem = async (row: UserRow) => {
    try {
      await deleteUser(row.accessKey)
      message.success(t("Delete Success"))
      table.resetRowSelection()
      await getDataList()
    } catch (error) {
      console.error(error)
      const msg = (error as Error)?.message || t("Delete Failed")
      message.error(msg)
    }
  }

  const deleteByList = () => {
    if (!selectedKeys.length) return
    dialog.error({
      title: t("Warning"),
      content: t("Are you sure you want to delete all selected users?"),
      positiveText: t("Confirm"),
      negativeText: t("Cancel"),
      onPositiveClick: async () => {
        const results = await Promise.allSettled(selectedKeys.map((key) => deleteUser(key)))
        const failures = results.filter((result) => result.status === "rejected")

        if (failures.length === 0) {
          message.success(t("Delete Success"))
          table.resetRowSelection()
        } else {
          const firstFailure = failures[0]
          const error = firstFailure?.status === "rejected" ? firstFailure.reason : undefined
          console.error(error)
          message.error((error as Error)?.message || t("Delete Failed"))
        }
        await getDataList()
      },
    })
  }

  const addToGroup = () => {
    setAddToGroupOpen(true)
  }

  return (
    <Page>
      <PageHeader
        actions={
          <>
            <SearchInput
              value={searchTerm}
              onChange={setSearchTerm}
              placeholder={t("Search Access User")}
              clearable
              className="max-w-xs"
            />
            <Button
              type="button"
              variant="outline"
              disabled={!canBulkDeleteUsers || !selectedKeys.length}
              onClick={deleteByList}
            >
              <RiDeleteBin5Line className="size-4" aria-hidden />
              {t("Delete Selected")}
            </Button>
            <Button
              type="button"
              variant="outline"
              disabled={!canAssignGroups || !selectedKeys.length}
              onClick={addToGroup}
            >
              <RiGroup2Fill className="size-4" aria-hidden />
              {t("Add to Group")}
            </Button>
            {canCreateUser ? (
              <Button type="button" variant="outline" onClick={() => setNewFormOpen(true)}>
                <RiAddLine className="size-4" aria-hidden />
                {t("Add User")}
              </Button>
            ) : null}
          </>
        }
      >
        <h1 className="text-2xl font-bold">{t("Users")}</h1>
      </PageHeader>

      <div className="space-y-4">
        <DataTable
          table={table}
          isLoading={loading}
          emptyTitle={t("No Data")}
          emptyDescription={t("Create a user to get started")}
          tableClass="min-w-full"
        />
        <DataTablePagination table={table} />

        <UserNewForm open={newFormOpen} onOpenChange={setNewFormOpen} onSuccess={getDataList} />
        <UserEditForm open={editFormOpen} onOpenChange={setEditFormOpen} row={editRow} onSuccess={getDataList} />
        <UserAddToGroupForm
          open={addToGroupOpen}
          onOpenChange={setAddToGroupOpen}
          selectedUsers={selectedKeys}
          onSuccess={() => {
            table.resetRowSelection()
            getDataList()
          }}
        />
      </div>
    </Page>
  )
}
