import { useLimits } from '@documenso/ee/server-only/limits/provider/client';
import { useUpdateSearchParams } from '@documenso/lib/client-only/hooks/use-update-search-params';
import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/organisation';
import { formatTemplatesPath } from '@documenso/lib/utils/teams';
import type { TFindTemplatesResponse } from '@documenso/trpc/server/template-router/schema';
import { Alert, AlertDescription, AlertTitle } from '@documenso/ui/primitives/alert';
import { Checkbox } from '@documenso/ui/primitives/checkbox';
import type { DataTableColumnDef, RowSelectionState } from '@documenso/ui/primitives/data-table';
import { DataTable } from '@documenso/ui/primitives/data-table';
import { DataTablePagination } from '@documenso/ui/primitives/data-table-pagination';
import { Skeleton } from '@documenso/ui/primitives/skeleton';
import { TableCell } from '@documenso/ui/primitives/table';
import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { AlertTriangle, Building2Icon, Globe2Icon, InfoIcon, Link2Icon, Loader, LockIcon } from 'lucide-react';
import { useMemo, useTransition } from 'react';
import { Link } from 'react-router';

import { TemplateType } from '~/components/general/template/template-type';
import { useCurrentTeam } from '~/providers/team';

import { TemplateUseDialog } from '../dialogs/template-use-dialog';
import { TemplateDirectLinkBadge } from '../general/template/template-direct-link-badge';
import { TemplatesTableActionDropdown } from './templates-table-action-dropdown';

type TemplatesTableProps = {
  data?: TFindTemplatesResponse;
  isLoading?: boolean;
  isLoadingError?: boolean;
  documentRootPath: string;
  templateRootPath: string;
  enableSelection?: boolean;
  rowSelection?: RowSelectionState;
  onRowSelectionChange?: (selection: RowSelectionState) => void;
};

type TemplatesTableRow = TFindTemplatesResponse['data'][number];

export const TemplatesTable = ({
  data,
  isLoading,
  isLoadingError,
  documentRootPath,
  templateRootPath,
  enableSelection,
  rowSelection,
  onRowSelectionChange,
}: TemplatesTableProps) => {
  const { _, i18n } = useLingui();
  const { remaining } = useLimits();

  const team = useCurrentTeam();
  const organisation = useCurrentOrganisation();

  const [isPending, startTransition] = useTransition();

  const updateSearchParams = useUpdateSearchParams();

  const formatTemplateLink = (row: TemplatesTableRow) => {
    const path = formatTemplatesPath(team.url);

    return `${path}/${row.envelopeId}`;
  };

  const columns = useMemo(() => {
    const cols: DataTableColumnDef<TemplatesTableRow>[] = [];

    if (enableSelection) {
      cols.push({
        id: 'select',
        header: ({ table }) => (
          <Checkbox
            checked={table.getIsAllPageRowsSelected()}
            onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
            aria-label={_(msg`Select all`)}
            onClick={(e) => e.stopPropagation()}
          />
        ),
        cell: ({ row }) => (
          <Checkbox
            checked={row.getIsSelected()}
            onCheckedChange={(value) => row.toggleSelected(!!value)}
            aria-label={_(msg`Select row`)}
            onClick={(e) => e.stopPropagation()}
          />
        ),
        enableSorting: false,
        enableHiding: false,
        size: 40,
      });
    }

    cols.push(
      {
        header: _(msg`Created`),
        accessorKey: 'createdAt',
        cell: ({ row }) => i18n.date(row.original.createdAt),
      },
      {
        header: _(msg`Title`),
        cell: ({ row }) => (
          <Link
            to={formatTemplateLink(row.original)}
            className="block max-w-[10rem] cursor-pointer truncate font-medium hover:underline md:max-w-[20rem]"
          >
            {row.original.title}
          </Link>
        ),
      },
      {
        header: () => (
          <div className="flex flex-row items-center">
            <Trans>Type</Trans>
            <Tooltip>
              <TooltipTrigger>
                <InfoIcon className="mx-2 h-4 w-4" />
              </TooltipTrigger>

              <TooltipContent className="!p-0 max-w-md space-y-2 text-foreground">
                <ul className="space-y-0.5 divide-y text-muted-foreground [&>li]:p-4">
                  <li>
                    <h2 className="mb-2 flex flex-row items-center font-semibold">
                      <Globe2Icon className="mr-2 h-5 w-5 text-green-500 dark:text-green-300" />
                      <Trans>Public</Trans>
                    </h2>

                    <p>
                      <Trans>
                        Public templates are connected to your public profile. Any modifications to public templates
                        will also appear in your public profile.
                      </Trans>
                    </p>
                  </li>
                  <li>
                    <div className="mb-2 flex w-fit flex-row items-center rounded border border-neutral-300 bg-neutral-200 px-1.5 py-0.5 text-xs dark:border-neutral-500 dark:bg-neutral-600">
                      <Link2Icon className="mr-1 h-3 w-3" />
                      <Trans>direct link</Trans>
                    </div>

                    <p>
                      <Trans>
                        Direct link templates contain one dynamic recipient placeholder. Anyone with access to this link
                        can sign the document, and it will then appear on your documents page.
                      </Trans>
                    </p>
                  </li>
                  <li>
                    <h2 className="mb-2 flex flex-row items-center font-semibold">
                      <LockIcon className="mr-2 h-5 w-5 text-blue-600 dark:text-blue-300" />
                      {team?.id ? <Trans>Team Only</Trans> : <Trans>Private</Trans>}
                    </h2>

                    <p>
                      {team?.id ? (
                        <Trans>Team only templates are not linked anywhere and are visible only to your team.</Trans>
                      ) : (
                        <Trans>Private templates can only be modified and viewed by you.</Trans>
                      )}
                    </p>
                  </li>
                  <li>
                    <h2 className="mb-2 flex flex-row items-center font-semibold">
                      <Building2Icon className="mr-2 h-5 w-5 text-orange-500 dark:text-orange-300" />
                      <Trans>Organisation</Trans>
                    </h2>

                    <p>
                      <Trans>
                        Organisation templates are shared across all teams within the same organisation. Only the owning
                        team can edit them.
                      </Trans>
                    </p>
                  </li>
                </ul>
              </TooltipContent>
            </Tooltip>
          </div>
        ),
        accessorKey: 'type',
        cell: ({ row }) => {
          const isFromOtherTeam = row.original.teamId !== team?.id;

          return (
            <div className="flex flex-row items-center">
              <TemplateType type={row.original.type} />

              {isFromOtherTeam && row.original.team?.name && (
                <span className="ml-2 text-muted-foreground text-xs">({row.original.team.name})</span>
              )}

              {row.original.directLink?.token && (
                <TemplateDirectLinkBadge
                  className="ml-2"
                  token={row.original.directLink.token}
                  enabled={row.original.directLink.enabled}
                />
              )}
            </div>
          );
        },
      },
      {
        header: _(msg`Actions`),
        accessorKey: 'actions',
        cell: ({ row }) => {
          return (
            <div className="flex items-center gap-x-4">
              <TemplateUseDialog
                envelopeId={row.original.envelopeId}
                templateId={row.original.id}
                templateSigningOrder={row.original.templateMeta?.signingOrder}
                documentDistributionMethod={row.original.templateMeta?.distributionMethod}
                recipients={row.original.recipients}
                documentRootPath={documentRootPath}
              />

              <TemplatesTableActionDropdown row={row.original} teamId={team?.id} templateRootPath={templateRootPath} />
            </div>
          );
        },
      },
    );

    return cols;
  }, [documentRootPath, team?.id, templateRootPath, enableSelection]);

  const onPaginationChange = (page: number, perPage: number) => {
    startTransition(() => {
      updateSearchParams({
        page,
        perPage,
      });
    });
  };

  const results = data ?? {
    data: [],
    perPage: 10,
    currentPage: 1,
    totalPages: 1,
  };

  return (
    <div className="relative">
      {remaining.documents === 0 && (
        <Alert variant="warning" className="mb-4">
          <AlertTriangle className="h-4 w-4" />
          <AlertTitle>
            <Trans>Document Limit Exceeded!</Trans>
          </AlertTitle>
          <AlertDescription className="mt-2">
            <Trans>
              You have reached your document limit.{' '}
              <Link className="underline underline-offset-4" to={`/o/${organisation.url}/settings/billing`}>
                Upgrade your account to continue!
              </Link>
            </Trans>
          </AlertDescription>
        </Alert>
      )}

      <DataTable
        columns={columns}
        data={results.data}
        perPage={results.perPage}
        currentPage={results.currentPage}
        totalPages={results.totalPages}
        onPaginationChange={onPaginationChange}
        enableRowSelection={enableSelection}
        rowSelection={rowSelection}
        onRowSelectionChange={onRowSelectionChange}
        getRowId={(row) => row.envelopeId}
        error={{
          enable: isLoadingError || false,
        }}
        skeleton={{
          enable: isLoading || false,
          rows: 5,
          component: (
            <>
              {enableSelection && (
                <TableCell className="w-10">
                  <Skeleton className="h-4 w-4 rounded" />
                </TableCell>
              )}
              <TableCell>
                <Skeleton className="h-4 w-40 rounded-full" />
              </TableCell>
              <TableCell>
                <Skeleton className="h-4 w-20 rounded-full" />
              </TableCell>
              <TableCell className="py-4">
                <div className="flex w-full flex-row items-center">
                  <Skeleton className="h-10 w-10 flex-shrink-0 rounded-full" />
                </div>
              </TableCell>
              <TableCell>
                <Skeleton className="h-4 w-20 rounded-full" />
              </TableCell>
              <TableCell>
                <Skeleton className="h-10 w-24 rounded" />
              </TableCell>
            </>
          ),
        }}
      >
        {(table) => <DataTablePagination additionalInformation="VisibleCount" table={table} />}
      </DataTable>

      {isPending && (
        <div className="absolute inset-0 flex items-center justify-center bg-white/50">
          <Loader className="h-8 w-8 animate-spin text-gray-500" />
        </div>
      )}
    </div>
  );
};
