import {
  Alert,
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
} from "@mui/material";
import React from "react";
import {
  AccommodationReservation,
  AccommodationsReservationsApi,
  UpdateAccommodationReservation,
} from "../../api/accommodations/AccommodationsReservationsApi";
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
import { fmtUnixDate } from "../../utils/time_utils";
import { useFamily } from "../../widgets/BaseFamilyRoute";
import { useAccommodations } from "../../widgets/accommodations/BaseAccommodationsRoute";
import { PropDateInput } from "../../widgets/forms/PropDateInput";
import { PropSelect } from "../../widgets/forms/PropSelect";

export function UpdateReservationDialog(p: {
  open: boolean;
  create: boolean;
  reservation?: UpdateAccommodationReservation;
  onClose: () => void;
  onSubmitted: (c: UpdateAccommodationReservation) => void;
}): React.ReactElement {
  const alert = useAlert();

  const family = useFamily();
  const accommodations = useAccommodations();

  const [reservation, setReservation] = React.useState<
    UpdateAccommodationReservation | undefined
  >();

  const [conflicts, setConflicts] = React.useState<
    AccommodationReservation[] | undefined
  >(undefined);

  const clearForm = () => {
    setReservation(undefined);
  };

  const cancel = () => {
    clearForm();
    p.onClose();
  };

  const submit = async () => {
    clearForm();
    p.onSubmitted(reservation!);
  };

  React.useEffect(() => {
    if (!reservation) setReservation(p.reservation);
  }, [p.open, p.reservation]);

  React.useEffect(() => {
    setConflicts(undefined);
    (async () => {
      try {
        if (
          !reservation ||
          reservation.accommodation_id < 1 ||
          reservation.start < 1 ||
          reservation.start > reservation.end
        ) {
          setConflicts([]);
          return;
        }

        setConflicts(
          (
            await AccommodationsReservationsApi.ReservationsForInterval(
              family.family,
              accommodations.accommodations.get(reservation.accommodation_id)!,
              reservation.start,
              reservation.end
            )
          ).filter(
            (r) =>
              r.id !== p.reservation?.reservation_id && r.validated !== false
          )
        );
      } catch (e) {
        console.error(e);
        alert(
          "Echec de la vérification de la présence de conflits de calendrier !"
        );
      }
    })();
  }, [
    p.open,
    reservation?.accommodation_id,
    reservation?.start,
    reservation?.end,
  ]);

  return (
    <Dialog open={p.open} onClose={cancel}>
      <DialogTitle>
        {p.create ? "Création" : "Mise à jour"} d'une réservation
      </DialogTitle>
      <DialogContent style={{ display: "flex", flexDirection: "column" }}>
        <PropSelect
          editing={p.create}
          label="Logement ciblé"
          onValueChange={(v) => {
            setReservation((a) => {
              return {
                ...a!,
                accommodation_id: Number(v),
              };
            });
          }}
          options={accommodations.accommodations.openToReservationList.map(
            (a) => {
              return { label: a.name, value: a.id.toString() };
            }
          )}
          value={
            reservation?.accommodation_id === -1
              ? ""
              : reservation?.accommodation_id?.toString()
          }
        />

        <PropDateInput
          editable
          label="Date de début"
          value={reservation?.start}
          onChange={(s) => {
            setReservation((r) => {
              return { ...r!, start: s ?? -1 };
            });
          }}
          minDate={Math.floor(new Date().getTime() / 1000) - 3600 * 24 * 60}
          canSetMiddleDay
        />

        <PropDateInput
          editable
          label="Date de fin"
          value={reservation?.end}
          lastSecOfDay={true}
          onChange={(s) => {
            setReservation((r) => {
              return { ...r!, end: s ?? -1 };
            });
          }}
          minDate={reservation?.start}
          canSetMiddleDay
        />

        {conflicts && conflicts.length > 0 && (
          <Alert severity="error">
            <p>
              Cette réservation est en conflit avec d'autres réservations sur
              les intervalles suivants :
            </p>
            <ul>
              {conflicts.map((c, num) => (
                <li key={num}>
                  Réservation du {fmtUnixDate(c.reservation_start)} au{" "}
                  {fmtUnixDate(c.reservation_end)}
                </li>
              ))}
            </ul>
          </Alert>
        )}
      </DialogContent>
      <DialogActions>
        <Button onClick={cancel}>Annuler</Button>
        <Button
          onClick={submit}
          disabled={
            !(
              (reservation?.accommodation_id ?? -1) > 0 &&
              (reservation?.start ?? -1) > 0 &&
              (reservation?.end ?? -1) > (reservation?.start ?? 0) &&
              (conflicts?.length ?? 0) === 0
            )
          }
        >
          {p.create ? "Créer" : "Mettre à jour"}
        </Button>
      </DialogActions>
    </Dialog>
  );
}
