import { useCallback, useEffect, useMemo, useState } from "react"
import { Pause, Play, Plus, RefreshCw } from "lucide-react"

import { ArcadiaError, useArcadiaClient } from "@crema/arcadia-client"
import {
  ActionsCell,
  BadgeCell,
  DataTable,
  DateCell,
  Pagination,
  useTable,
  type ActionItem,
  type BadgeTone,
  type Column,
} from "@crema/table-ui"
import { SearchInput } from "@crema/search-ui"
import { AlertBanner, ConfirmDialog, EmptyState, LoadingOverlay } from "@crema/feedback-ui"

import { AppShell } from "~/components/layout/app-shell"
import { PageHeader } from "~/components/layout/page-header"
import { Button } from "~/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "~/components/ui/card"
import {
  activateTenant,
  deactivateTenant,
  listTenants,
  suspendTenant,
  type Tenant,
  type TenantStatus,
} from "~/lib/arcadia/tenants"
import { pageTitle } from "~/lib/page-meta"
import { useSession } from "~/lib/session"
import { useRegisterAdminContext } from "~/lib/admin-context"

export const meta = () => pageTitle("Tenants")

type PendingAction = {
  kind: "suspend" | "deactivate"
  tenant: Tenant
} | null

export default function TenantsRoute() {
  const session = useSession()
  const arcadia = useArcadiaClient()

  const [tenants, setTenants] = useState<Tenant[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [pending, setPending] = useState<PendingAction>(null)
  const [search, setSearch] = useState("")

  const refresh = useCallback(async () => {
    setError(null)
    setLoading(true)
    try {
      const list = await listTenants(arcadia)
      setTenants(list)
    } catch (err) {
      setError(err instanceof ArcadiaError ? err.message : "Failed to load tenants.")
    } finally {
      setLoading(false)
    }
  }, [arcadia])

  useEffect(() => {
    if (session) refresh()
  }, [session, refresh])

  const runAction = useCallback(
    async (action: PendingAction) => {
      if (!action) return
      try {
        if (action.kind === "suspend") await suspendTenant(arcadia, action.tenant.id)
        else await deactivateTenant(arcadia, action.tenant.id)
        setPending(null)
        await refresh()
      } catch (err) {
        setError(err instanceof ArcadiaError ? err.message : "Action failed.")
        setPending(null)
      }
    },
    [arcadia, refresh],
  )

  const columns = useMemo<Column<Tenant>[]>(
    () => [
      {
        id: "name",
        header: "Name",
        accessor: "name",
        sortable: true,
        cell: (t) => <span className="font-medium">{t.name}</span>,
      },
      {
        id: "slug",
        header: "Slug",
        accessor: "slug",
        sortable: true,
        cell: (t) => (
          <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">{t.slug}</code>
        ),
      },
      {
        id: "status",
        header: "Status",
        accessor: "status",
        sortable: true,
        cell: (t) => <BadgeCell label={t.status} tone={statusTone(t.status)} />,
      },
      {
        id: "plan",
        header: "Plan",
        accessor: (t) => t.plan?.name ?? "",
        sortable: true,
        cell: (t) => <span className="text-muted-foreground">{t.plan?.name ?? "—"}</span>,
      },
      {
        id: "created",
        header: "Created",
        accessor: "inserted_at",
        sortable: true,
        cell: (t) => <DateCell value={t.inserted_at} format="short" />,
      },
      {
        id: "actions",
        header: "",
        align: "right",
        cell: (t) => (
          <ActionsCell
            items={rowActions(t, arcadia, refresh, setPending, setError)}
            triggerDataAction={`tenant-${t.slug}-actions`}
          />
        ),
      },
    ],
    [arcadia, refresh],
  )

  const tenantSummary = useMemo(
    () => ({
      total: tenants.length,
      byStatus: tenants.reduce<Record<string, number>>((acc, t) => {
        acc[t.status] = (acc[t.status] ?? 0) + 1
        return acc
      }, {}),
      tenants: tenants.map((t) => ({
        id: t.id,
        slug: t.slug,
        name: t.name,
        status: t.status,
        plan: t.plan?.name ?? null,
        inserted_at: t.inserted_at,
      })),
    }),
    [tenants],
  )
  useRegisterAdminContext("tenants", tenantSummary)

  const table = useTable<Tenant>({
    data: tenants,
    columns,
    getRowId: (t) => t.id,
    initialPageSize: 25,
    initialSearch: search,
  })
  // Keep useTable's search in lockstep with our SearchInput.
  useEffect(() => {
    table.setSearch(search)
  }, [search, table])

  return (
    <AppShell>
      <PageHeader
        title="Tenants"
        description="Multi-tenant workspaces on this arcadia deployment."
        actions={
          <>
            <Button
              variant="outline"
              size="sm"
              onClick={refresh}
              disabled={loading}
              data-action="tenants-refresh"
            >
              <RefreshCw className={`size-4 ${loading ? "animate-spin" : ""}`} />
              Refresh
            </Button>
            <Button size="sm" disabled data-action="tenants-create">
              <Plus className="size-4" />
              New tenant
            </Button>
          </>
        }
      />

        {error ? (
          <AlertBanner variant="error" dismissible onDismiss={() => setError(null)}>
            {error}
          </AlertBanner>
        ) : null}

        <Card>
          <CardHeader className="flex flex-row items-center justify-between gap-4">
            <SearchInput
              value={search}
              onValueChange={setSearch}
              placeholder="Search by name, slug, or status"
              data-action="tenants-search"
              className="max-w-sm flex-1"
            />
            <div className="text-xs text-muted-foreground">
              {table.total} of {tenants.length}
            </div>
          </CardHeader>

          <CardContent className="relative p-0">
            <LoadingOverlay active={loading && tenants.length === 0} label="Loading tenants…" />
            {table.total === 0 && !loading ? (
              <EmptyState
                title={search ? "No tenants match that search." : "No tenants yet."}
                description={
                  search ? "Try a different name, slug, or status." : "Create your first tenant to get started."
                }
                className="py-12"
              />
            ) : (
              <>
                <DataTable
                  columns={columns}
                  rows={table.pageRows}
                  getRowId={(t) => t.id}
                  sort={table.sort}
                  onSortToggle={table.toggleSort}
                  loading={loading && tenants.length > 0}
                  stickyHeader
                />
                <Pagination
                  page={table.page}
                  pageSize={table.pageSize}
                  total={table.total}
                  onPageChange={table.setPage}
                  onPageSizeChange={table.setPageSize}
                />
              </>
            )}
          </CardContent>
        </Card>

      <ConfirmDialog
        open={pending?.kind === "suspend"}
        onOpenChange={(o) => !o && setPending(null)}
        title="Suspend tenant?"
        description={
          pending
            ? `${pending.tenant.name} will be suspended. Members won't be able to sign in until you reactivate.`
            : ""
        }
        confirmLabel="Suspend"
        variant="default"
        onConfirm={() => runAction(pending)}
      />
      <ConfirmDialog
        open={pending?.kind === "deactivate"}
        onOpenChange={(o) => !o && setPending(null)}
        title="Deactivate tenant?"
        description={
          pending
            ? `${pending.tenant.name} will be deactivated. This is more severe than suspending.`
            : ""
        }
        confirmLabel="Deactivate"
        variant="danger"
        onConfirm={() => runAction(pending)}
      />
    </AppShell>
  )
}

function statusTone(status: TenantStatus): BadgeTone {
  if (status === "active") return "success"
  if (status === "suspended") return "warning"
  if (status === "deactivated") return "danger"
  return "default"
}

function rowActions(
  t: Tenant,
  arcadia: ReturnType<typeof useArcadiaClient>,
  refresh: () => Promise<void>,
  setPending: (p: PendingAction) => void,
  setError: (msg: string | null) => void,
): ActionItem[] {
  const items: ActionItem[] = []
  if (t.status === "active") {
    items.push({
      id: "suspend",
      label: "Suspend",
      icon: <Pause className="size-4" />,
      dataAction: `tenant-${t.slug}-suspend`,
      onSelect: () => setPending({ kind: "suspend", tenant: t }),
    })
  } else {
    items.push({
      id: "activate",
      label: "Activate",
      icon: <Play className="size-4" />,
      dataAction: `tenant-${t.slug}-activate`,
      onSelect: async () => {
        try {
          await activateTenant(arcadia, t.id)
          await refresh()
        } catch (err) {
          setError(err instanceof ArcadiaError ? err.message : "Activate failed.")
        }
      },
    })
  }
  items.push({
    id: "deactivate",
    label: "Deactivate",
    destructive: true,
    dataAction: `tenant-${t.slug}-deactivate`,
    onSelect: () => setPending({ kind: "deactivate", tenant: t }),
  })
  return items
}
