"use client";

import Container from "@/components/elements/Container";
import RoundedButton from "@/components/elements/RoundedButton";
import LocalePageShell from "@/components/i18n/LocalePageShell";
import PageTitle from "@/components/settings/PageTitle";
import { buildStorageUrl } from "@/components/main/BaseUrl";
import useAxios from "@/hooks/useAxios";
import Image from "next/image";
import { useParams, useRouter } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
import toast from "react-hot-toast";
import { useTranslation } from "react-i18next";

type BookingService = {
  serviceId: string;
  title: string;
  price: number;
  image?: string | null;
};

type BookingConfig = {
  _id: string;
  services: BookingService[];
  weeklySchedule: { day: string; ranges: { start_time: string; end_time: string }[] }[];
  holidayDates: string[];
  depositRequired: boolean;
};

type TimeSlot = { start_time: string; end_time: string };

const DAY_KEYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];

function buildUpcomingDates(
  config: BookingConfig,
  repeatExpiresAt: string | null,
  count = 21
) {
  const openDays = new Set(config.weeklySchedule.map((entry) => entry.day));
  const holidaySet = new Set(config.holidayDates.map((d) => d.slice(0, 10)));
  const expiresAtTime = repeatExpiresAt ? new Date(repeatExpiresAt).getTime() : null;
  const dates: string[] = [];
  const cursor = new Date();

  for (let i = 0; i < 60 && dates.length < count; i++) {
    const date = new Date(cursor);
    date.setDate(cursor.getDate() + i);
    if (expiresAtTime !== null && date.getTime() >= expiresAtTime) break;
    const iso = date.toISOString().slice(0, 10);
    const dayKey = DAY_KEYS[date.getDay()];
    if (openDays.has(dayKey) && !holidaySet.has(iso)) {
      dates.push(iso);
    }
  }
  return dates;
}

function BookingFlowPage() {
  const { t } = useTranslation("common");
  const router = useRouter();
  const { request, loading } = useAxios();
  const params = useParams<{ userId: string }>();

  const [config, setConfig] = useState<BookingConfig | null | undefined>(undefined);
  const [repeatExpiresAt, setRepeatExpiresAt] = useState<string | null>(null);
  const [step, setStep] = useState<"service" | "datetime" | "confirm">("service");
  const [selectedService, setSelectedService] = useState<BookingService | null>(null);
  const [selectedDate, setSelectedDate] = useState<string | null>(null);
  const [slots, setSlots] = useState<TimeSlot[] | null>(null);
  const [selectedSlot, setSelectedSlot] = useState<TimeSlot | null>(null);

  useEffect(() => {
    request<{ config: BookingConfig | null; repeatExpiresAt?: string | null }>(
      "GET",
      `/bookings/public/${params.userId}`
    ).then((res) => {
      setConfig(res?.config ?? null);
      setRepeatExpiresAt(res?.repeatExpiresAt ?? null);
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [params.userId]);

  const upcomingDates = useMemo(
    () => (config ? buildUpcomingDates(config, repeatExpiresAt) : []),
    [config, repeatExpiresAt]
  );

  useEffect(() => {
    if (!config || !selectedDate) return;
    setSlots(null);
    setSelectedSlot(null);
    request<{ slots: TimeSlot[] }>(
      "GET",
      `/bookings/availability?configId=${config._id}&date=${selectedDate}`
    ).then((res) => setSlots(res?.slots || []));
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedDate, config]);

  const handleConfirm = async () => {
    if (!config || !selectedService || !selectedDate || !selectedSlot) return;
    try {
      const res = await request<{ booking: { _id: string; depositRequired: boolean } }>(
        "POST",
        "/bookings/book",
        {
          configId: config._id,
          serviceId: selectedService.serviceId,
          date: selectedDate,
          startTime: selectedSlot.start_time,
          endTime: selectedSlot.end_time,
        }
      );

      const booking = res?.booking;
      if (!booking) return;

      if (booking.depositRequired) {
        const payRes = await request<{ paymentUrl?: string }>(
          "POST",
          "/bookings/payment/initiate",
          { bookingId: booking._id }
        );
        if (payRes?.paymentUrl) {
          window.location.href = payRes.paymentUrl;
        }
        return;
      }

      toast.success(t("booking.bookingConfirmed"));
      router.push(`/users/${params.userId}`);
    } catch (err: unknown) {
      const message =
        (err as { response?: { data?: { message?: string } } })?.response
          ?.data?.message || t("shops.unknownError");
      toast.error(message);
    }
  };

  return (
    <LocalePageShell>
      <Container>
        <PageTitle>{t("booking.bookOnline")}</PageTitle>

        {config === undefined ? (
          <p className="py-10 text-center text-sm text-neutral-500">
            {t("common.loading")}
          </p>
        ) : !config ? (
          <p className="py-10 text-center text-sm text-neutral-500">
            {t("booking.emptyList")}
          </p>
        ) : (
          <div className="mt-6 text-sm">
            {step === "service" && (
              <div className="flex flex-col gap-2">
                <p className="mb-2 font-bold">{t("booking.selectService")}</p>
                {config.services.map((service) => (
                  <button
                    type="button"
                    key={service.serviceId}
                    onClick={() => {
                      setSelectedService(service);
                      setStep("datetime");
                    }}
                    className="flex items-center justify-between rounded-2xl border border-neutral-200 p-3 dark:border-neutral-700"
                  >
                    <div className="flex items-center gap-2">
                      {service.image && (
                        <Image
                          src={buildStorageUrl(service.image)}
                          width={40}
                          height={40}
                          alt={service.title}
                          className="rounded-lg"
                        />
                      )}
                      <span className="font-semibold">{service.title}</span>
                    </div>
                    <span className="text-neutral-500">
                      {Number(service.price).toLocaleString()} {t("settings.toman")}
                    </span>
                  </button>
                ))}
              </div>
            )}

            {step === "datetime" && selectedService && (
              <div className="flex flex-col gap-4">
                <p className="font-bold">{t("booking.selectDateTime")}</p>
                <div className="flex gap-2 overflow-x-auto pb-2">
                  {upcomingDates.map((date) => (
                    <button
                      type="button"
                      key={date}
                      onClick={() => setSelectedDate(date)}
                      className={`flex-shrink-0 rounded-xl border px-3 py-2 text-xs ${
                        selectedDate === date
                          ? "border-[#0095f6] bg-[#0095f6]/10 font-bold"
                          : "border-neutral-200 dark:border-neutral-700"
                      }`}
                    >
                      {date}
                    </button>
                  ))}
                </div>

                {selectedDate && (
                  <div>
                    {slots === null ? (
                      <p className="text-neutral-500">{t("common.loading")}</p>
                    ) : slots.length === 0 ? (
                      <p className="text-neutral-500">
                        {t("booking.noAvailableSlots")}
                      </p>
                    ) : (
                      <div className="flex flex-wrap gap-2">
                        {slots.map((slot) => (
                          <button
                            type="button"
                            key={`${slot.start_time}-${slot.end_time}`}
                            onClick={() => {
                              setSelectedSlot(slot);
                              setStep("confirm");
                            }}
                            className={`rounded-xl border px-3 py-2 text-xs ${
                              selectedSlot?.start_time === slot.start_time
                                ? "border-[#0095f6] bg-[#0095f6]/10 font-bold"
                                : "border-neutral-200 dark:border-neutral-700"
                            }`}
                          >
                            {slot.start_time} - {slot.end_time}
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                )}
              </div>
            )}

            {step === "confirm" && selectedService && selectedDate && selectedSlot && (
              <div className="flex flex-col gap-4">
                <p className="font-bold">{t("booking.confirmBooking")}</p>
                <div className="rounded-2xl border border-neutral-200 p-4 dark:border-neutral-700">
                  <div className="flex justify-between py-1">
                    <span>{t("booking.selectService")}</span>
                    <span className="font-semibold">{selectedService.title}</span>
                  </div>
                  <div className="flex justify-between py-1">
                    <span>{t("booking.selectDateTime")}</span>
                    <span className="font-semibold">
                      {selectedDate} — {selectedSlot.start_time}-{selectedSlot.end_time}
                    </span>
                  </div>
                  <div className="flex justify-between py-1">
                    <span>{t("settings.toman")}</span>
                    <span className="font-semibold">
                      {Number(selectedService.price).toLocaleString()}
                    </span>
                  </div>
                  {config.depositRequired && (
                    <div className="mt-2 flex justify-between border-t border-neutral-200 pt-2 dark:border-neutral-700">
                      <span>{t("booking.depositAmountLabel")}</span>
                      <span className="font-bold">
                        {Math.round(selectedService.price * 0.3).toLocaleString()}{" "}
                        {t("settings.toman")}
                      </span>
                    </div>
                  )}
                </div>
                <RoundedButton
                  variant="primary"
                  className="h-10"
                  disabled={loading}
                  onClick={handleConfirm}
                >
                  {config.depositRequired
                    ? t("booking.payDeposit")
                    : t("booking.confirmBooking")}
                </RoundedButton>
              </div>
            )}
          </div>
        )}
      </Container>
    </LocalePageShell>
  );
}

export default BookingFlowPage;
