import { FolderType } from '@documenso/lib/types/folder-type';
import { formatTemplatesPath } from '@documenso/lib/utils/teams';
import { trpc } from '@documenso/trpc/react';
import type { TFolderWithSubfolders } from '@documenso/trpc/server/folder-router/schema';
import { Input } from '@documenso/ui/primitives/input';
import { msg } from '@lingui/core/macro';
import { Trans, useLingui } from '@lingui/react/macro';
import { FolderIcon, HomeIcon, Loader2, SearchIcon } from 'lucide-react';
import { useState } from 'react';
import { Link, useSearchParams } from 'react-router';

import { FolderCreateDialog } from '~/components/dialogs/folder-create-dialog';
import { FolderDeleteDialog } from '~/components/dialogs/folder-delete-dialog';
import { FolderMoveDialog } from '~/components/dialogs/folder-move-dialog';
import { FolderUpdateDialog } from '~/components/dialogs/folder-update-dialog';
import { FolderCard } from '~/components/general/folder/folder-card';
import { useCurrentTeam } from '~/providers/team';
import { appMetaTags } from '~/utils/meta';

export function meta() {
  return appMetaTags(msg`Templates`);
}

export default function TemplatesFoldersPage() {
  const { t } = useLingui();

  const team = useCurrentTeam();
  const [searchParams] = useSearchParams();

  const parentId = searchParams.get('parentId');

  const [isMovingFolder, setIsMovingFolder] = useState(false);
  const [folderToMove, setFolderToMove] = useState<TFolderWithSubfolders | null>(null);
  const [isDeletingFolder, setIsDeletingFolder] = useState(false);
  const [folderToDelete, setFolderToDelete] = useState<TFolderWithSubfolders | null>(null);
  const [isSettingsFolderOpen, setIsSettingsFolderOpen] = useState(false);
  const [folderToSettings, setFolderToSettings] = useState<TFolderWithSubfolders | null>(null);
  const [searchTerm, setSearchTerm] = useState('');

  const { data: foldersData, isLoading: isFoldersLoading } = trpc.folder.getFolders.useQuery({
    type: FolderType.TEMPLATE,
    parentId: parentId,
  });

  const normalizedSearchTerm = searchTerm.trim().toLowerCase();

  const isFolderMatchingSearch = (folder: TFolderWithSubfolders) =>
    folder.name.toLowerCase().includes(normalizedSearchTerm);

  const filteredFolders = foldersData?.folders.filter(isFolderMatchingSearch) ?? [];
  const pinnedFolders = filteredFolders.filter((folder) => folder.pinned);
  const unpinnedFolders = filteredFolders.filter((folder) => !folder.pinned);
  const hasFolders = (foldersData?.folders.length ?? 0) > 0;
  const hasSearchResults = filteredFolders.length > 0;

  const formatBreadcrumbPath = (folderId: string) => {
    const templatesPath = formatTemplatesPath(team.url);

    return `${templatesPath}/f/${folderId}`;
  };

  return (
    <div className="mx-auto w-full max-w-screen-xl px-4 md:px-8">
      <div className="flex w-full items-center justify-between">
        <div className="flex flex-1 items-center font-medium text-muted-foreground text-sm">
          <Link to={formatTemplatesPath(team.url)} className="flex items-center hover:text-muted-foreground/80">
            <HomeIcon className="mr-2 h-4 w-4" />
            <Trans>Home</Trans>
          </Link>

          {foldersData?.breadcrumbs.map((folder) => (
            <div key={folder.id} className="flex items-center">
              <span className="px-3">/</span>
              <Link to={formatBreadcrumbPath(folder.id)} className="flex items-center hover:text-muted-foreground/80">
                <FolderIcon className="mr-2 h-4 w-4" />
                <span>{folder.name}</span>
              </Link>
            </div>
          ))}
        </div>

        <div className="flex flex-col gap-y-4 sm:flex-row sm:justify-end sm:gap-x-4">
          <FolderCreateDialog type={FolderType.TEMPLATE} parentFolderId={parentId} />
        </div>
      </div>

      <div className="relative w-full max-w-md py-6">
        <SearchIcon className="absolute top-9 left-2 h-4 w-4 text-muted-foreground" />
        <Input
          placeholder={t`Search folders...`}
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          className="pl-8"
        />
      </div>

      <h1 className="mt-4 truncate font-semibold text-2xl md:text-3xl">
        <Trans>All Folders</Trans>
      </h1>

      {isFoldersLoading ? (
        <div className="mt-6 flex justify-center">
          <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
        </div>
      ) : (
        <>
          {pinnedFolders.length > 0 && (
            <div className="mt-6">
              <div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
                {pinnedFolders.map((folder) => (
                  <FolderCard
                    key={folder.id}
                    folder={folder}
                    onMove={(folder) => {
                      setFolderToMove(folder);
                      setIsMovingFolder(true);
                    }}
                    onSettings={(folder) => {
                      setFolderToSettings(folder);
                      setIsSettingsFolderOpen(true);
                    }}
                    onDelete={(folder) => {
                      setFolderToDelete(folder);
                      setIsDeletingFolder(true);
                    }}
                  />
                ))}
              </div>
            </div>
          )}

          <div>
            {searchTerm && !hasSearchResults && (
              <div className="mt-6 text-center text-muted-foreground">
                <Trans>No folders found matching "{searchTerm}"</Trans>
              </div>
            )}

            {!searchTerm && !hasFolders && (
              <div className="mt-6 text-center text-muted-foreground">
                <Trans>No folders yet.</Trans>
              </div>
            )}

            <div className="mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
              {unpinnedFolders.map((folder) => (
                <FolderCard
                  key={folder.id}
                  folder={folder}
                  onMove={(folder) => {
                    setFolderToMove(folder);
                    setIsMovingFolder(true);
                  }}
                  onSettings={(folder) => {
                    setFolderToSettings(folder);
                    setIsSettingsFolderOpen(true);
                  }}
                  onDelete={(folder) => {
                    setFolderToDelete(folder);
                    setIsDeletingFolder(true);
                  }}
                />
              ))}
            </div>
          </div>
        </>
      )}

      <FolderMoveDialog
        foldersData={foldersData?.folders}
        folder={folderToMove}
        isOpen={isMovingFolder}
        onOpenChange={(open: boolean) => {
          setIsMovingFolder(open);

          if (!open) {
            setFolderToMove(null);
          }
        }}
      />

      <FolderUpdateDialog
        folder={folderToSettings}
        isOpen={isSettingsFolderOpen}
        onOpenChange={(open: boolean) => {
          setIsSettingsFolderOpen(open);

          if (!open) {
            setFolderToSettings(null);
          }
        }}
      />

      {folderToDelete && (
        <FolderDeleteDialog
          folder={folderToDelete}
          isOpen={isDeletingFolder}
          onOpenChange={(open: boolean) => {
            setIsDeletingFolder(open);

            if (!open) {
              setFolderToDelete(null);
            }
          }}
        />
      )}
    </div>
  );
}
