import toast from "react-hot-toast";
import type { AnnunciId } from "~/schemas/public/Annunci";
import { api } from "~/utils/api";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "~/components/ui/dialog";
import { Button } from "~/components/ui/button";
import { LoadingPage } from "~/components/loading";
import { MultiSelect } from "~/components/custom_ui/multiselect";
import { add } from "date-fns";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "~/components/ui/alert-dialog";
import { Calculator, ClockAlert, Plus } from "lucide-react";
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
import {
  Credenza,
  CredenzaBody,
  CredenzaContent,
  CredenzaDescription,
  CredenzaHeader,
  CredenzaTitle,
  CredenzaTrigger,
} from "~/components/custom_ui/credenza";

import { useState } from "react";
import { useServizio } from "~/providers/ServizioProvider";

export const ServizioActions = () => {
  const { servizio, isAdmin } = useServizio();

  const canUserEdit =
    servizio.isOkAcconto &&
    servizio.decorrenza !== null &&
    !servizio.annunci.some((a) => a.user_confirmed_at !== null);

  if (!isAdmin && !canUserEdit) {
    return null; // If the user is not an admin and cannot edit, do not render the actions
  }
  return (
    <div className="flex w-full flex-wrap justify-start gap-3 sm:justify-end">
      {(isAdmin || canUserEdit) && (
        <>
          <EditPreferenze />
          <InterruzioneServizio />
        </>
      )}
      {isAdmin && <AddAnnuncio />}
    </div>
  );
};
const AddAnnuncio = () => {
  const { servizioId, userId } = useServizio();

  const { data: codici, isLoading: loading } =
    api.servizio.getAnnunciAvailableToAdd.useQuery({
      servizioId,
    });

  const [selectedAnnunci, setSelectedAnnunci] = useState<
    { value: AnnunciId; label: string }[]
  >([]);

  const [openModal, setOpenModal] = useState(false);

  const utils = api.useUtils();
  const { mutate } = api.servizio.addServizioAnnunci.useMutation({
    onSuccess: async () => {
      await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
      await utils.servizio.getAnnunciAvailableToAdd.invalidate({
        servizioId,
      });
      await utils.servizio.getCompatibileAnnunci.invalidate({
        servizioId,
      });
      toast.success("Annuncio aggiunto");
      setOpenModal(false);
      setSelectedAnnunci([]);
    },
    onError: (error) => {
      console.error(error);
      toast.error("Errore durante l'aggiunta dell'annuncio");
    },
  });

  return (
    <Dialog open={openModal} onOpenChange={setOpenModal}>
      <DialogTrigger asChild>
        <Button
          aria-label="Add Annuncio"
          variant="outline"
          onClick={() => {
            setSelectedAnnunci([]);
          }}
          className="items-center gap-2"
        >
          <Plus />
          Annuncio
        </Button>
      </DialogTrigger>
      <DialogContent className="sm:max-w-[425px]">
        <DialogHeader>
          <DialogTitle>Aggiungi annuncio</DialogTitle>
          <DialogDescription>
            Salva un annuncio nella ricerca dell&apos;utente
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4 py-4">
          {loading ? (
            <LoadingPage />
          ) : (
            <MultiSelect
              elementId="select-annuncio"
              elementName="annuncio"
              isMulti={true}
              placeholder=""
              defaultValue={undefined}
              options={
                codici?.map((cod) => ({
                  label: cod.codice,
                  value: cod.id.toString(),
                })) || []
              }
              onValueChange={(value) => {
                setSelectedAnnunci(
                  value.map((v) => ({
                    value: parseInt(v.value) as AnnunciId,
                    label: v.label,
                  })),
                );
              }}
            />
          )}
        </div>
        <DialogFooter>
          <Button
            aria-label="Cancel Add Annuncio"
            type="button"
            onClick={() => {
              if (!selectedAnnunci.length) return;
              mutate({
                servizioId,
                annunci: selectedAnnunci.map((annuncio) => annuncio.value),
              });
            }}
            disabled={!selectedAnnunci.length}
          >
            Aggiungi
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
};
const InterruzioneServizio = () => {
  const { servizio, userId } = useServizio();

  const beforeInterruzioneLimit =
    servizio.decorrenza != null &&
    new Date() <=
      add(servizio.decorrenza, {
        days: 14,
      });

  const utils = api.useUtils();
  const { mutate } = api.servizio.interruzioneServizio.useMutation({
    onSuccess: async () => {
      await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
      toast.success("Interruzione richiesta");
    },
    onError: (error) => {
      console.error(error);
      toast.error("Errore durante la richiesta di interruzione");
    },
  });

  return (
    <AlertDialog>
      <AlertDialogTrigger asChild>
        <Button
          aria-label="Request Interruzione"
          variant="outline"
          className="items-center gap-2"
          disabled={!beforeInterruzioneLimit}
        >
          <ClockAlert /> <span>Interruzione</span>
        </Button>
      </AlertDialogTrigger>
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>
            Sei sicuro di voler richiedere l&apos;interruzione?
          </AlertDialogTitle>
          <AlertDialogDescription>
            Questa azione è irreversibile e comporta la disattivazione dei
            servizi attivati. Confermando l&apos;azione recedi dal servizio
            secondo le condizioni contrattuali. Verrai notificato via email
            della conferma dell&apos;avvenuta interruzione.
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Annulla</AlertDialogCancel>
          <AlertDialogAction
            aria-label="Confirm Interruzione"
            onClick={() => mutate({ servizioId: servizio.servizio_id })}
          >
            Continua
          </AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  );
};

const EditPreferenze = () => {
  const { servizioId, userId, isAdmin } = useServizio();
  const [openEditPreferenze, setOpenEditPreferenze] = useState(false);
  const { data, isLoading } = api.servizio.getServizio.useQuery({ servizioId });
  const utils = api.useUtils();

  const { mutate: update } = api.servizio.updateServizio.useMutation({
    onSuccess: async () => {
      toast.success("Servizio modificato con successo");
      await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
      await utils.servizio.getServizio.invalidate({ servizioId });
      await utils.servizio.getCompatibileAnnunci.invalidate({
        servizioId,
      });
      setOpenEditPreferenze(false);
    },
    onError: (error) => {
      toast.error(error.message);
    },
  });

  function onSubmit(fields: FormValues) {
    update({
      servizioId,
      data: {
        ...fields,
      },
    });
  }

  return (
    <Credenza open={openEditPreferenze} onOpenChange={setOpenEditPreferenze}>
      <CredenzaTrigger asChild>
        <Button
          aria-label="Preferenze di ricerca"
          className="items-center gap-2"
        >
          <Calculator />
          Preferenze
        </Button>
      </CredenzaTrigger>
      <CredenzaContent className="max-h-[90vh] w-full sm:max-w-5xl">
        <CredenzaHeader>
          <CredenzaTitle>Preferenze di ricerca</CredenzaTitle>
          <CredenzaDescription className="sr-only">
            Preferenze
          </CredenzaDescription>
        </CredenzaHeader>
        <CredenzaBody className="max-h-[80vh] w-full overflow-y-auto pb-5">
          {isLoading ? (
            <LoadingPage />
          ) : (
            <FormNewServizio
              initialData={data}
              onSubmit={onSubmit}
              isLimited={!isAdmin}
            />
          )}
        </CredenzaBody>
      </CredenzaContent>
    </Credenza>
  );
};
