'use client';

import { useState } from 'react';
import { useRouter, useParams } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { useQueryClient } from '@tanstack/react-query';
import { Plus } from 'lucide-react';
import type { ServiceSummary } from '@/types/api';
import { useBookingDraft } from '@/lib/store/booking-draft';
import { bookingApi, addressApi } from '@/lib/api';
import { useAuth } from '@/components/auth/AuthProvider';
import { useWizardContext } from '@/hooks/useWizardContext';
import { reportObservability } from '@/hooks/useObservability';
import { VendorAddToEventPanel, type AddToEventSubmission } from '@/components/vendor/VendorAddToEventPanel';

type AddToEventButtonProps = {
  service: Pick<ServiceSummary, 'public_id' | 'name' | 'product_type'>;
  variant?: 'card' | 'sticky';
  className?: string;
};

export function AddToEventButton({ service, variant = 'card', className }: AddToEventButtonProps) {
  const t = useTranslations('vendor.add_to_event');
  const router = useRouter();
  const params = useParams<{ locale: string }>();
  const locale = params?.locale ?? 'en';
  const queryClient = useQueryClient();
  const [open, setOpen] = useState(false);
  const [feedback, setFeedback] = useState<string | null>(null);

  const setBooking = useBookingDraft((s) => s.setBooking);
  const bookingPublicId = useBookingDraft((s) => s.bookingPublicId);
  const { wizardContext } = useWizardContext();
  const { status } = useAuth();

  const handleClick = () => {
    // B1 — the token is HttpOnly, so gate on the resolved auth status instead of
    // reading the cookie. `unknown` means the session probe is still in flight;
    // treat it as not-yet-authenticated and send to login.
    if (status !== 'authenticated') {
      // Logged-out: hand off to login with a return URL.
      router.push(`/${locale}/auth/login?next=${encodeURIComponent(window.location.pathname)}`);
      return;
    }
    setOpen(true);
  };

  const ensureDraftAndAddItem = async (payload: AddToEventSubmission) => {
    let draftId = bookingPublicId;

    if (!draftId) {
      if (!wizardContext?.occasionPublicId || !wizardContext.eventDate || !wizardContext.cityPublicId) {
        // Missing prerequisites — route to the wizard so the user fills the
        // minimum required fields, then return here.
        const back = encodeURIComponent(window.location.pathname);
        router.push(`/${locale}/wizard?return=${back}&service=${service.public_id}`);
        throw new Error(t('need_wizard'));
      }

      const addresses = await addressApi.list(locale).catch(() => []);
      const defaultAddress = addresses.find((a) => a.is_default) ?? addresses[0];

      if (!defaultAddress) {
        router.push(`/${locale}/me/addresses?next=${encodeURIComponent(window.location.pathname)}`);
        throw new Error(t('need_address'));
      }

      const startsAt = `${wizardContext.eventDate}T18:00:00`;
      const endsAt = `${wizardContext.eventDate}T23:00:00`;

      const draft = await bookingApi.create(locale, {
        occasion_id: wizardContext.occasionPublicId,
        event_starts_at: startsAt,
        event_ends_at: endsAt,
        guest_count: wizardContext.guestCount ?? undefined,
        celebrant_name: wizardContext.celebrantName ?? undefined,
        address: {
          // Feature 054 (US7) — Backend CreateBookingDraftRequest now requires
          // ULID. `CustomerAddressRow.city_id` is widened to `number | string`
          // because the response carries ULIDs; coerce to string just in case.
          city_id: String(defaultAddress.city_id),
          address_line: defaultAddress.address_line,
          building: defaultAddress.building ?? undefined,
          floor: defaultAddress.floor ?? undefined,
          apartment: defaultAddress.apartment ?? undefined,
          landmark: defaultAddress.landmark ?? undefined,
          recipient_name: defaultAddress.recipient_name,
          recipient_phone_e164: defaultAddress.recipient_phone_e164,
        },
      });

      setBooking(draft);
      draftId = draft.public_id;
    }

    await bookingApi.addItem(locale, draftId, payload);
    // Re-fetch draft so subscribers (cart pill, sticky banners) see the new item count.
    const refreshed = await bookingApi.show(locale, draftId);
    setBooking(refreshed);
    void queryClient.invalidateQueries({ queryKey: ['booking-draft'] });
  };

  const handleSubmit = async (payload: AddToEventSubmission) => {
    try {
      await ensureDraftAndAddItem(payload);
      setOpen(false);
      setFeedback(t('added_to_cart'));
      setTimeout(() => setFeedback(null), 3000);
    } catch (err) {
      reportObservability('vendor.add_to_event.failed', {
        servicePublicId: service.public_id,
        error: err instanceof Error ? err.message : String(err),
      });
      throw err;
    }
  };

  const buttonClass =
    variant === 'sticky'
      ? `btn-primary w-full text-center block ${className ?? ''}`
      : `inline-flex items-center justify-center gap-1.5 rounded-md bg-primary-600 px-3 py-2 text-sm font-semibold text-white transition-colors hover:bg-primary-700 ${className ?? ''}`;

  return (
    <>
      <button
        type="button"
        onClick={handleClick}
        className={buttonClass}
        data-testid={variant === 'sticky' ? 'vendor-add-to-event-mobile' : 'vendor-add-to-event-card'}
      >
        {variant === 'card' ? <Plus className="h-4 w-4" aria-hidden /> : null}
        <span>{t('button')}</span>
      </button>

      {feedback ? (
        <p
          role="status"
          aria-live="polite"
          className="mt-1 text-xs text-success"
          data-testid="vendor-add-to-event-feedback"
        >
          {feedback}
        </p>
      ) : null}

      <VendorAddToEventPanel
        open={open}
        service={service}
        defaultStartsAt={
          wizardContext?.eventDate ? `${wizardContext.eventDate}T18:00` : null
        }
        defaultEndsAt={
          wizardContext?.eventDate ? `${wizardContext.eventDate}T23:00` : null
        }
        defaultRecipientName={null}
        defaultRecipientPhone={null}
        onClose={() => setOpen(false)}
        onSubmit={handleSubmit}
      />
    </>
  );
}
