import { useState } from "react";
import { AreaRiservataLayout } from "~/components/Layout";
import { LoadingPage } from "~/components/loading";
import type { NextPageWithLayout } from "~/pages/_app";
import { api } from "~/utils/api";
import { ChevronsUpDown, RefreshCcw } from "lucide-react";
import { Status500 } from "~/components/status-page";
import { StorageTable } from "~/components/tables/storage-table";
import type {
  Storageindex,
  StorageindexId,
} from "~/schemas/public/Storageindex";
import { Button } from "~/components/ui/button";
import { useTranslation } from "~/providers/I18nProvider";

import toast from "react-hot-toast";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "~/components/ui/dialog";
import { Separator } from "~/components/ui/separator";
import { cn } from "~/lib/utils";
import {
  CommandInput,
  CommandItem,
  CommandList,
  CommandEmpty,
  CommandGroup,
  Command,
} from "~/components/ui/command";
import type { Users } from "~/schemas/public/Users";
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "~/components/ui/popover";
import {
  StorageTableProvider,
  useStorageTable,
  type StorageTable as StorageTableType,
} from "~/providers/StorageTableProvider";
import { UploadModal } from "~/components/upload_modal";
import { UserAvatar } from "~/components/user_avatar";

const AdminStorage: NextPageWithLayout = () => {
  const { data, isLoading, refetch } = api.storage.getAll.useQuery();
  const { t } = useTranslation();
  const utils = api.useUtils();
  const { mutate: deleteFile } = api.storage.deleteStorage.useMutation({
    onMutate: () => {
      const toastId = toast.loading(t.caricamento, {
        icon: "🪛",
      });
      return { toastId };
    },
    onSuccess: async (_error, _variables, context) => {
      await utils.storage.getAll.invalidate();

      toast.success(t.allegati.allegato_rimosso, {
        icon: "🗑️",
        id: context?.toastId,
      });
    },
  });

  const handleDelete = (id: StorageindexId) => {
    deleteFile({ storageId: id });
  };

  const handleRefetch = async () => {
    await refetch();
  };

  if (isLoading) return <LoadingPage />;
  if (!data) return <Status500 />;
  //magari query amche file ownership per poter filtrare in tab se da admin o da utente o una lista di utenti a cui è visibile il file
  return (
    <StorageTableProvider>
      <div className="mx-1 flex-1 overflow-auto">
        <div className="mx-auto py-8">
          <StorageTableHeader
            handleRefetch={handleRefetch}
            handleDelete={handleDelete}
          />

          <StorageTable data={data} handleDelete={handleDelete} />
        </div>
      </div>
    </StorageTableProvider>
  );
};
export default AdminStorage;

const StorageTableHeader = ({
  handleRefetch,
  handleDelete,
}: {
  handleRefetch: () => Promise<void>;
  handleDelete: (id: StorageindexId) => void;
}) => {
  const { table } = useStorageTable();
  if (!table) return null;
  return (
    <div className="mx-3 flex flex-wrap items-center justify-between gap-3">
      <div className="flex max-w-lg items-center gap-3">
        <h3 className="text-accent-foreground text-xl font-bold sm:text-2xl">
          Impostazioni
        </h3>
        <button
          onClick={async () => {
            await handleRefetch();
            table.resetRowSelection();
          }}
          className="hover:scale-110"
        >
          <RefreshCcw className="size-6" />
        </button>
      </div>
      <div className="flex max-w-lg flex-wrap items-center gap-3">
        <UploadModal
          cb_onUpload={() => {
            table.setRowSelection({});
          }}
        />
        <Actions handleDelete={handleDelete} table={table} />
      </div>
    </div>
  );
};

AdminStorage.getLayout = function getLayout(page) {
  return <AreaRiservataLayout>{page}</AreaRiservataLayout>;
};

const Actions = ({
  handleDelete,
  table,
}: {
  handleDelete: (id: StorageindexId) => void;
  table: StorageTableType;
}) => {
  const { selectedRows } = useStorageTable();
  const [visbOpen, setVisbOpen] = useState(false);

  const deleteSelected = () => {
    selectedRows.forEach((row) => handleDelete(row.id));
    table.resetRowSelection();
  };

  return (
    <div className="flex items-center gap-4 md:mt-0">
      <Button
        disabled={selectedRows.length === 0}
        variant="info"
        className="transition-all duration-100"
        onClick={() => setVisbOpen(true)}
      >
        Modifica Visibilità
      </Button>

      <Button
        disabled={selectedRows.length === 0}
        variant="destructive"
        onClick={() => deleteSelected()}
        className="transition-all duration-100"
      >
        Elimina
      </Button>
      {visbOpen && (
        <VisibComponent
          allegati={selectedRows}
          open={visbOpen}
          setOpen={setVisbOpen}
        />
      )}
    </div>
  );
};

const VisibComponent = ({
  allegati,
  open,
  setOpen,
}: {
  allegati: Storageindex[];
  open: boolean;
  setOpen: (v: boolean) => void;
}) => {
  const utils = api.useUtils();
  const { data, isLoading } = api.storage.getStorageVisibility.useQuery({
    storageIds: allegati.map((a) => a.id),
  });
  const { data: users } = api.users.getUsers.useQuery();

  const { mutate: remove } = api.storage.removeStorageVisibility.useMutation({
    onMutate: () => {
      const toastId = toast.loading("Rimozione utente in corso", {
        icon: "🪛",
      });
      return { toastId };
    },
    onSuccess: async (_error, _variables, context) => {
      await utils.storage.getStorageVisibility.invalidate();
      toast.success("Utente rimosso", {
        icon: "🗑️",
        id: context?.toastId,
      });
    },
  });
  const { mutate: add } = api.storage.addStorageVisibility.useMutation({
    onMutate: () => {
      const toastId = toast.loading("Aggiunta utente in corso", {
        icon: "🪛",
      });
      return { toastId };
    },
    onSuccess: async (_error, _variables, context) => {
      await utils.storage.getStorageVisibility.invalidate();
      toast.success("Utente aggiunto", {
        icon: "👍",
        id: context?.toastId,
      });
    },
  });

  const { mutate: reset } = api.storage.resetStorageVisibility.useMutation({
    onMutate: () => {
      const toastId = toast.loading("Reset visibilità in corso", {
        icon: "🪛",
      });
      return { toastId };
    },
    onSuccess: async (_error, _variables, context) => {
      await utils.storage.getStorageVisibility.invalidate();
      toast.success("Reset effettuato", {
        icon: "👍",
        id: context?.toastId,
      });
    },
  });

  return (
    <>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent className="max-w-2xl">
          <DialogHeader>
            <DialogTitle>Modifica Visibilità</DialogTitle>
            <DialogDescription className="sr-only">
              Modifica la visibilità degli allegati selezionati
            </DialogDescription>
          </DialogHeader>
          <div className="flex flex-col gap-4">
            {isLoading ? (
              <LoadingPage />
            ) : (
              <>
                <div className="flex items-center gap-3">
                  <p>Seleziona utente:</p>
                  <UtentiCombo
                    users={users || []}
                    onSelect={(user) => {
                      for (const allegato of allegati) {
                        add({ userId: user.id, storageId: allegato.id });
                      }
                    }}
                  />
                  <Button
                    variant="destructive"
                    className="ml-auto"
                    onClick={() =>
                      reset({ storageId: allegati.map((a) => a.id) })
                    }
                  >
                    Reset
                  </Button>
                </div>
                {data?.map((allegato, i) => (
                  <div
                    key={allegato.id}
                    className={cn(
                      "flex flex-col gap-3 rounded-md p-2",
                      i % 2 === 0 && "bg-gray-200",
                    )}
                  >
                    <p className="text-lg font-semibold">
                      File: {allegato.filename}
                    </p>
                    <div className="flex items-center gap-3">
                      <p>Visibile a:</p>
                      {allegato.users_storages.length === 0 ? (
                        <p>Nessuno</p>
                      ) : (
                        <ul className="flex gap-2">
                          {allegato.users_storages.map((user) => (
                            <li key={user.userid}>
                              <Button
                                variant="outline"
                                className="after:content-['X']"
                                onClick={() =>
                                  remove({
                                    userId: user.userid,
                                    storageId: allegato.id,
                                  })
                                }
                              >
                                {user.username}
                              </Button>
                            </li>
                          ))}
                        </ul>
                      )}
                    </div>
                  </div>
                ))}
              </>
            )}
            <Separator />
          </div>
        </DialogContent>
      </Dialog>
    </>
  );
};

const UtentiCombo = ({
  users,
  onSelect,
}: {
  users: Users[];
  onSelect: (user: Users) => void;
}) => {
  const [open, setOpen] = useState(false);

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          variant="outline"
          role="combobox"
          aria-expanded={open}
          className="w-auto justify-between"
        >
          Seleziona utente...
          <ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-auto p-0">
        <Command>
          <CommandInput placeholder="Cerca Utente..." />
          <CommandList>
            <CommandEmpty>Nessun utente.</CommandEmpty>
            <CommandGroup>
              {users.map((user) => (
                <CommandItem
                  key={user.id}
                  value={user.id}
                  onSelect={(currentValue) => {
                    onSelect(users.find((u) => u.id === currentValue)!);
                    setOpen(false);
                  }}
                >
                  <span className="flex items-center gap-2">
                    <UserAvatar
                      className="size-8"
                      userId={user.id}
                      username={user.username}
                    />

                    <span>
                      <span className="block font-medium">{user.username}</span>
                    </span>
                  </span>
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
};
