import React from "react";
import { useParams } from "react-router-dom";
import { DeliveryChoiceFlow } from "../components/client/DeliveryChoiceFlow";
import { DeliverySlotsPicker } from "../components/client/DeliverySlotsPicker";
import { PickupSlotsPicker } from "../components/client/PickupSlotsPicker";
import { OrderCompositionPanel } from "../components/client/OrderCompositionPanel";
import { getInvitationReferenceLabel } from "../components/client/invitationReference";
import { DeliveryStateNotice } from "../components/client/DeliveryStateNotice";
import { Panel } from "../components/UI/Panel";

import { Skeleton } from "../components/UI/Loading";
import { formatDeliveryDate } from "../components/client/deliveryDateFormatting";
import {
  confirmDeliveryChoice,
  fetchDeliveryInvitation,
} from "../services/deliveryInvitationApi";

const DELIVERY_TIMEZONE = "Europe/Simferopol";

const getBusinessTodayKey = (referenceDate = new Date()) => {
  const parts = new Intl.DateTimeFormat("en-CA", {
    timeZone: DELIVERY_TIMEZONE,
    year: "numeric",
    month: "2-digit",
    day: "2-digit",
  }).formatToParts(referenceDate);

  const year = parts.find((part) => part.type === "year")?.value || "";
  const month = parts.find((part) => part.type === "month")?.value || "";
  const day = parts.find((part) => part.type === "day")?.value || "";

  return `${year}-${month}-${day}`;
};

const addDaysToDateKey = (dateKey, amount) => {
  const baseDate = new Date(`${dateKey}T12:00:00Z`);
  if (Number.isNaN(baseDate.getTime())) {
    return "";
  }

  baseDate.setUTCDate(baseDate.getUTCDate() + amount);
  return baseDate.toISOString().slice(0, 10);
};

const isSundayKey = (dateKey) => {
  if (!dateKey) return true;
  const d = new Date(`${dateKey}T12:00:00Z`);
  return d.getUTCDay() === 0;
};

const getNextWorkdayKey = (dateKey) => {
  let next = addDaysToDateKey(dateKey, 1);
  while (isSundayKey(next)) {
    next = addDaysToDateKey(next, 1);
  }
  return next;
};

const getAllowedDeliveryDateKeys = (referenceDate = new Date()) => {
  const todayKey = getBusinessTodayKey(referenceDate);
  const firstWorkday = getNextWorkdayKey(todayKey);
  const secondWorkday = getNextWorkdayKey(firstWorkday);
  return new Set([firstWorkday, secondWorkday].filter(Boolean));
};

const isAllowedDeliverySlotDate = (dateKey, referenceDate = new Date()) => {
  if (!dateKey) {
    return false;
  }

  return getAllowedDeliveryDateKeys(referenceDate).has(dateKey);
};

export const groupSlotsFromInvitation = (invitation, referenceDate = new Date()) => {
  if (!invitation) {
    return [];
  }

  const rawSlots = Array.isArray(invitation.availableSlots) ? invitation.availableSlots : [];
  const deliveryDate = invitation.deliveryDate;
  const deliveryTime = invitation.deliveryTime;

  if (!rawSlots.length && !deliveryDate) {
    // Fallback: generate default delivery slots (next 2 workdays, both halves, skip Sunday)
    const todayKey = getBusinessTodayKey(referenceDate);
    const firstWorkday = getNextWorkdayKey(todayKey);
    const secondWorkday = getNextWorkdayKey(firstWorkday);
    return [
      { id: `slot-${firstWorkday}-first`, date: firstWorkday, time: "Первая половина дня" },
      { id: `slot-${firstWorkday}-second`, date: firstWorkday, time: "Вторая половина дня" },
      { id: `slot-${secondWorkday}-first`, date: secondWorkday, time: "Первая половина дня" },
      { id: `slot-${secondWorkday}-second`, date: secondWorkday, time: "Вторая половина дня" },
    ].filter((s) => s.date);
  }

  if (!rawSlots.length && deliveryDate) {
    return [
      {
        id: `slot-${deliveryDate}-${deliveryTime || "default"}`,
        date: deliveryDate,
        time: deliveryTime || "Половина дня",
      },
    ];
  }

  return rawSlots
    .map((raw, index) => {
      if (typeof raw === "string") {
        const parts = raw.split(",");
        const datePart = parts[0]?.trim() || "";
        const timePart = parts.slice(1).join(",").trim() || "";

        const parsedDate = datePart.replace(/[а-яё]+/gi, "").trim()
          || deliveryDate
          || "";

        if (!isAllowedDeliverySlotDate(parsedDate, referenceDate)) {
          return null;
        }

        return {
          id: `slot-${index}-${raw}`,
          date: parsedDate || deliveryDate || "",
          time: timePart || deliveryTime || raw,
        };
      }

      if (raw && typeof raw === "object") {
        const slotId = typeof raw.id === "string" ? raw.id : `slot-${index}-${deliveryDate || "custom"}`;
        const slotDate = typeof raw.date === "string" ? raw.date : deliveryDate || "";
        const slotTime = typeof raw.time === "string"
          ? raw.time
          : typeof raw.label === "string"
            ? raw.label
            : deliveryTime || "";

        if (!slotDate && !slotTime) {
          return null;
        }

        if (!isAllowedDeliverySlotDate(slotDate, referenceDate)) {
          return null;
        }

        return {
          id: slotId,
          date: slotDate,
          time: slotTime,
        };
      }

      return null;
    })
    .filter(Boolean);
};

export const buildDeliveryConfirmationPayload = ({
  slot,
  invitation,
  searchDate,
  deliveryType = "delivery",
  pickupDate,
  pickupTimeSlot,
}) => {
  if (deliveryType === "pickup") {
    return {
      deliveryType: "pickup",
      pickupDate: pickupDate || slot?.date || undefined,
      pickupTimeSlot: pickupTimeSlot || slot?.time || undefined,
      deliveryDate: pickupDate || slot?.date || searchDate || invitation?.deliveryDate || undefined,
      deliveryTime: pickupTimeSlot || slot?.time || undefined,
    };
  }

  return {
    deliveryType: "delivery",
    deliveryDate: slot?.date || searchDate || invitation?.deliveryDate || undefined,
    deliveryTime: slot?.time || invitation?.deliveryTime || undefined,
  };
};

export const buildSelectedSlotFromInvitation = (invitation, slots = []) => {
  if (!invitation?.deliveryDate) {
    return null;
  }

  const matchingSlot = slots.find(
    (slot) =>
      slot.date === invitation.deliveryDate &&
      (!invitation.deliveryTime || slot.time === invitation.deliveryTime),
  );

  return matchingSlot || {
    id: `slot-${invitation.deliveryDate}-${invitation.deliveryTime || "default"}`,
    date: invitation.deliveryDate,
    time: invitation.deliveryTime || "Половина дня",
  };
};

export const getClientDeliveryHeroDescription = (isActiveState, isChoiceSaved) => {
  if (isChoiceSaved) {
    return "";
  }

  return isActiveState
    ? "Вам предложены варианты доставки. Выберите удобную дату и время."
    : "По этому заказу согласование доставки завершено или передано логисту.";
};

const TAB_DELIVERY = "delivery";
const TAB_PICKUP = "pickup";

export const ClientDeliveryPage = () => {
  const { token } = useParams();
  const [invitation, setInvitation] = React.useState(null);
  const [loading, setLoading] = React.useState(Boolean(token));
  const [error, setError] = React.useState("");
  const [actionMessage, setActionMessage] = React.useState("");
  const [selectedSlotId, setSelectedSlotId] = React.useState(null);
  const [selectedSlot, setSelectedSlot] = React.useState(null);
  const [choiceSaved, setChoiceSaved] = React.useState(false);
  const [activeTab, setActiveTab] = React.useState(TAB_DELIVERY);
  const [deliveryAddress, setDeliveryAddress] = React.useState("");
  const referenceDate = React.useMemo(
    () => (invitation?.smsSentAt ? new Date(invitation.smsSentAt) : new Date()),
    [token, invitation?.smsSentAt],
  );

  React.useEffect(() => {
    let cancelled = false;

    const loadInvitation = async () => {
      if (!token) {
        setLoading(false);
        setError("Не передан токен приглашения.");
        return;
      }

      setLoading(true);
      setError("");
      setActionMessage("");
      setSelectedSlotId(null);
      setSelectedSlot(null);
      setChoiceSaved(false);

      try {
        const loadedInvitation = await fetchDeliveryInvitation(token);
        if (!cancelled) {
          setInvitation(loadedInvitation);
          // If invitation already has deliveryType=pickup, pre-select pickup tab
          if (loadedInvitation?.deliveryType === "pickup") {
            setActiveTab(TAB_PICKUP);
          }
        }
      } catch (fetchError) {
        if (!cancelled) {
          setInvitation(null);
          setError(fetchError instanceof Error ? fetchError.message : "Не удалось загрузить приглашение");
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    };

    loadInvitation();

    return () => {
      cancelled = true;
    };
  }, [token]);

  const slots = groupSlotsFromInvitation(invitation, referenceDate);

  const invitationState = invitation?.state || "awaiting_choice";
  const isActiveState = ["awaiting_choice", "opened", "reminder_sent"].includes(invitationState);

  const invitationSelectedSlot = isActiveState ? null : buildSelectedSlotFromInvitation(invitation, slots);

  const effectiveSelectedSlot = selectedSlot || invitationSelectedSlot;
  const isChoiceSaved = choiceSaved || (!isActiveState && Boolean(invitationSelectedSlot));
  const savedChoiceLabel = effectiveSelectedSlot
    ? `${formatDeliveryDate(effectiveSelectedSlot.date)} / ${effectiveSelectedSlot.time}`
    : "";
  const heroDescription = getClientDeliveryHeroDescription(isActiveState, isChoiceSaved);

  const handleSaveChoice = async () => {
    if (!token) {
      return;
    }

    if (!effectiveSelectedSlot) {
      setError("Сначала выберите дату и половину дня.");
      return;
    }

    setActionMessage("Сохраняем выбор...");
    setChoiceSaved(false);
    setError("");

    try {
      await confirmDeliveryChoice({
        token,
        deliveryTime: effectiveSelectedSlot.time,
        deliveryDate: effectiveSelectedSlot.date,
        deliveryType: activeTab,
        ...(activeTab === TAB_PICKUP ? {
          pickupDate: effectiveSelectedSlot.date,
          pickupTimeSlot: effectiveSelectedSlot.time,
        } : {}),
        ...(activeTab === TAB_DELIVERY && deliveryAddress.trim() ? {
          deliveryAddress: deliveryAddress.trim(),
        } : {}),
      });
      const loadedInvitation = await fetchDeliveryInvitation(token);
      setInvitation(loadedInvitation);
      setSelectedSlot(
        buildSelectedSlotFromInvitation(
          loadedInvitation,
          groupSlotsFromInvitation(loadedInvitation, referenceDate),
        ) || effectiveSelectedSlot,
      );
      setChoiceSaved(true);
      setActionMessage("Выбор сохранен, спасибо.");
    } catch (confirmError) {
      setActionMessage("");
      setError(confirmError instanceof Error ? confirmError.message : "Не удалось сохранить выбор");
    }
  };

  const handleSlotSelect = (slot) => {
    setSelectedSlotId(slot.id);
    setSelectedSlot(slot);
    setChoiceSaved(false);
    setActionMessage(
      `Выбрано: ${slot.date ? `${formatDeliveryDate(slot.date)} / ${slot.time}` : slot.time}`,
    );
    setError("");
  };

  if (loading) {
    return (
      <main className="min-h-screen bg-[var(--color-bg)] px-3 py-4 sm:px-6 sm:py-8">
        <div className="mx-auto flex w-full max-w-3xl flex-col gap-4">
          <Panel className="space-y-3 p-5 sm:p-6">
            <p className="text-sm uppercase tracking-[0.24em] text-[var(--color-text-muted)]">Доставка заказа</p>
            <h1 className="text-2xl font-semibold leading-tight sm:text-3xl">Загрузка страницы</h1>
            <div className="space-y-2 mt-4">
              <Skeleton className="w-full" />
              <Skeleton className="w-3/4" />
              <Skeleton className="w-1/2" />
            </div>
          </Panel>
          <Panel className="p-5 sm:p-6">
            <div className="space-y-3">
              <Skeleton variant="heading" className="w-2/3" />
              <Skeleton className="w-full" />
              <Skeleton className="w-1/2" />
            </div>
          </Panel>
        </div>
      </main>
    );
  }

  if (error && !invitation) {
    return (
      <main className="min-h-screen bg-[var(--color-bg)] px-3 py-4 sm:px-6 sm:py-8">
        <div className="mx-auto flex w-full max-w-3xl flex-col gap-4">
          <Panel className="space-y-3 p-5 sm:p-6">
            <p className="text-sm uppercase tracking-[0.24em] text-[var(--color-text-muted)]">Доставка заказа</p>
            <h1 className="text-2xl font-semibold leading-tight sm:text-3xl">Не удалось открыть страницу</h1>
            <p className="text-sm leading-6 text-[var(--color-text-muted)]">{error}</p>
          </Panel>
        </div>
      </main>
    );
  }

  return (
    <main className="min-h-screen bg-[var(--color-bg)] px-3 py-4 sm:px-6 sm:py-8">
      <div className="mx-auto flex w-full max-w-3xl flex-col gap-4">
{!isChoiceSaved ? (
          <Panel className="space-y-3 p-5 sm:p-6">
            <p className="text-sm uppercase tracking-[0.24em] text-[var(--color-text-muted)]">Доставка заказа</p>
            <h1 className="text-2xl font-semibold leading-tight sm:text-3xl">Согласование доставки</h1>
            {heroDescription ? (
              <p className="text-sm leading-6 text-[var(--color-text-muted)]">
                {heroDescription}
              </p>
            ) : null}
          </Panel>
        ) : null}

        <OrderCompositionPanel invitation={invitation} />

        {isChoiceSaved && savedChoiceLabel ? (
          <Panel className="space-y-2 p-5 sm:p-6">
            <p className="text-sm uppercase tracking-[0.24em] text-[var(--color-text-muted)]">Ваш выбор</p>
            <h2 className="text-xl font-semibold leading-tight">
              {invitation?.deliveryType === "pickup" ? "Самовывоз" : "Доставка"}: {savedChoiceLabel}
            </h2>
            <p className="text-sm leading-6 text-[var(--color-text-muted)]">
              {getInvitationReferenceLabel(invitation)}
            </p>
            <p className="text-sm leading-6 text-[var(--color-text-muted)]">
              Статус: {invitation?.deliveryType === "pickup" ? "самовывоз" : "доставка"} уже согласован. При повторном открытии этой ссылки будет показан тот же выбор.
            </p>
            {(invitation?.pickupCode || invitation?.pickup_code) ? (
              <div className="mt-3 rounded-2xl border-2 border-[var(--color-accent)] bg-[var(--color-accent-soft)] p-4 text-center">
                <p className="text-xs uppercase tracking-[0.2em] text-[var(--color-text-muted)]">Код выдачи</p>
                <p className="mt-1 text-3xl font-bold tracking-[0.4em] text-[var(--color-accent)]">{invitation.pickupCode || invitation.pickup_code}</p>
                <p className="mt-2 text-xs text-[var(--color-text-muted)]">Покажите этот код при получении заказа</p>
              </div>
            ) : null}
          </Panel>
        ) : null}

        {isActiveState && !isChoiceSaved ? (
          <>
            {/* Tab switcher */}
            <div className="flex gap-2 rounded-[28px] border border-[var(--color-border)] bg-[var(--color-surface)] p-1">
              <button
                type="button"
                className={`flex-1 rounded-[24px] px-4 py-2.5 text-sm font-semibold transition ${
                  activeTab === TAB_DELIVERY
                    ? "bg-[var(--color-accent)] text-white"
                    : "text-[var(--color-text-muted)] hover:text-[var(--color-text)]"
                }`}
                onClick={() => {
                  setActiveTab(TAB_DELIVERY);
                  setSelectedSlotId(null);
                  setSelectedSlot(null);
                  setActionMessage("");
                }}
              >
                🚚 Доставка
              </button>
              <button
                type="button"
                className={`flex-1 rounded-[24px] px-4 py-2.5 text-sm font-semibold transition ${
                  activeTab === TAB_PICKUP
                    ? "bg-[var(--color-accent)] text-white"
                    : "text-[var(--color-text-muted)] hover:text-[var(--color-text)]"
                }`}
                onClick={() => {
                  setActiveTab(TAB_PICKUP);
                  setSelectedSlotId(null);
                  setSelectedSlot(null);
                  setActionMessage("");
                }}
              >
                🏪 Самовывоз
              </button>
            </div>

            {activeTab === TAB_DELIVERY && !invitation?.deliveryAddress && !invitation?.customerAddress && (
              <Panel className="space-y-3 border-[rgba(239,68,68,0.3)] bg-[var(--color-surface)] p-5 sm:p-6">
                <div className="flex items-start gap-3">
                  <span className="text-xl">📍</span>
                  <div className="flex-1 space-y-2">
                    <p className="text-sm font-semibold uppercase tracking-[0.16em] text-[var(--color-text)]">Укажите адрес доставки</p>
                    <p className="text-sm leading-6 text-[var(--color-text-muted)]">
                      Адрес доставки отсутствует в заказе. Пожалуйста, введите полный адрес, куда нужно привезти заказ.
                    </p>
                  </div>
                </div>
                <input
                  type="text"
                  value={deliveryAddress}
                  onChange={(e) => setDeliveryAddress(e.target.value)}
                  placeholder="Город, улица, дом, квартира"
                  className="w-full rounded-xl border border-[var(--color-border)] bg-[var(--color-bg)] px-4 py-3 text-sm text-[var(--color-text)] placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)] focus:outline-none"
                />
              </Panel>
            )}

            {activeTab === TAB_DELIVERY && !invitation?.isPayedShip ? (
              <div className="rounded-2xl border border-[var(--color-warning)] bg-[var(--color-warning-soft)] p-4">
                <div className="flex items-start gap-3">
                  <span className="text-lg">💰</span>
                  <div>
                    <p className="text-sm font-semibold text-[var(--color-warning)]">
                      Стоимость доставки не оплачена
                    </p>
                    <p className="mt-1 text-sm text-[var(--color-text-muted)]">
                      Стоимость доставки будет рассчитана отдельно и согласована с логистом после выбора даты и времени.
                    </p>
                  </div>
                </div>
              </div>
            ) : null}

            {activeTab === TAB_DELIVERY && slots.length ? (
              <DeliverySlotsPicker
                slots={slots}
                onSelectSlot={handleSlotSelect}
                selectedSlotId={selectedSlotId}
              />
            ) : null}

            {activeTab === TAB_PICKUP ? (
              <PickupSlotsPicker
                onSelectSlot={handleSlotSelect}
                selectedSlotId={selectedSlotId}
                referenceDate={referenceDate}
              />
            ) : null}

            {activeTab === TAB_PICKUP && (invitation?.pickupCode || invitation?.pickup_code) ? (
              <div className="rounded-2xl border-2 border-[var(--color-accent)] bg-[var(--color-accent-soft)] p-4 text-center">
                <p className="text-xs uppercase tracking-[0.2em] text-[var(--color-text-muted)]">Код выдачи</p>
                <p className="mt-1 text-3xl font-bold tracking-[0.4em] text-[var(--color-accent)]">{invitation.pickupCode || invitation.pickup_code}</p>
                <p className="mt-2 text-xs text-[var(--color-text-muted)]">Покажите этот код при получении заказа</p>
              </div>
            ) : null}

            {activeTab === TAB_DELIVERY && !slots.length ? (
              <Panel className="p-5 sm:p-6">
                <p className="text-sm text-[var(--color-text-muted)]">Нет доступных слотов для выбора доставки.</p>
              </Panel>
            ) : null}
          </>
        ) : null}

        {isActiveState && !isChoiceSaved ? (
          <DeliveryChoiceFlow
            invitation={invitation}
            selectedSlot={effectiveSelectedSlot}
            onConfirmChoice={handleSaveChoice}
            deliveryType={activeTab}
          />
        ) : !isActiveState && !isChoiceSaved ? (
          <DeliveryStateNotice state={invitationState} />
        ) : null}

        {actionMessage ? (
          <Panel className="p-5 text-sm leading-6 text-[var(--color-text-muted)] sm:p-6">{actionMessage}</Panel>
        ) : null}

        {!loading && error && invitation ? (
          <Panel className="space-y-2 border-[rgba(204,112,0,0.28)] bg-[var(--color-surface)] p-5 sm:p-6">
            <p className="text-sm uppercase tracking-[0.24em] text-[var(--color-text-muted)]">
              Не удалось сохранить
            </p>
            <h2 className="text-2xl font-semibold leading-tight">
              Проверьте выбор еще раз
            </h2>
            <p className="text-sm leading-6 text-[var(--color-text-muted)]">{error}</p>
          </Panel>
        ) : null}
      </div>
    </main>
  );
};