/**
 * useAddDealActions — submit / archive / star-toggle handlers for AddDealShell.
 *
 * Pulled out of the shell to keep AddDealShell.tsx focused on orchestration + JSX.
 */
import { useCallback, useState } from 'react';
import type { UseFormReturn } from 'react-hook-form';
import type { LaunchMode } from '@/components/ui/primitives/LaunchModePicker';
import { captureCaught } from '@/lib/observability';
import { fetchWithRefresh } from '@/lib/api/refresh-on-401';
import { getCsrfToken } from '@/lib/csrf';
import type { AddDealFormValues } from './useAddDeal';
import { toIsoWithOffset } from './useAddDeal';
import { dealTypeCaps } from '@/lib/deal-types';

function nowAsLocalDatetime(): string {
  const now = new Date();
  const pad = (n: number) => String(n).padStart(2, '0');
  return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}T${pad(now.getHours())}:${pad(now.getMinutes())}`;
}

export interface UseAddDealActionsOptions {
  form: UseFormReturn<AddDealFormValues>;
  dealId: string | undefined;
  vendorId: string | undefined;
  isEditMode: boolean;
  draftId: string | null | undefined;
  launchMode: LaunchMode;
  calculatedPrice: string | null | undefined;
  successRedirect: string;
  saveNow: () => Promise<void>;
  /** Falls back to the hook's own submit when no vendorId is provided. */
  hookOnSubmit: () => void;
  /** Translation function for vendorDrafts namespace, captured from the shell. */
  tDrafts: (key: 'savingError') => string;
  /** Starred state + setter (lives in useAddDealEffects). */
  starred: boolean;
  setStarred: (v: boolean) => void;
}

export interface UseAddDealActionsResult {
  /** Wraps form.handleSubmit. Pass to <form onSubmit>. */
  handleSubmit: ReturnType<UseFormReturn<AddDealFormValues>['handleSubmit']>;
  starPending: boolean;
  toggleStar: () => Promise<void>;
  archivePending: boolean;
  onArchive: () => Promise<void>;
  submitPending: boolean;
  onSubmitForReview: () => Promise<void>;
}

export function useAddDealActions({
  form,
  dealId,
  vendorId,
  isEditMode,
  draftId,
  launchMode,
  calculatedPrice,
  successRedirect,
  saveNow,
  hookOnSubmit,
  tDrafts,
  starred,
  setStarred,
}: UseAddDealActionsOptions): UseAddDealActionsResult {
  const [starPending, setStarPending] = useState(false);
  const [archivePending, setArchivePending] = useState(false);
  const [submitPending, setSubmitPending] = useState(false);

  const handleSubmit = form.handleSubmit(async (values) => {
    const { quantity, ...restValues } = values;
    const effectiveWindowStart =
      launchMode === 'now'
        ? toIsoWithOffset(nowAsLocalDatetime())
        : toIsoWithOffset(values.windowStart);
    const body = {
      ...restValues,
      discountedPrice: calculatedPrice ?? '0',
      quantityTotal: quantity,
      windowStart: effectiveWindowStart,
      windowEnd: toIsoWithOffset(values.windowEnd),
    };

    if (vendorId && !isEditMode && draftId !== undefined) {
      // Always flush the latest form state before submitting so the server reads
      // current imageSet, pickupStart/End, etc. — autosave may have last fired
      // before the image upload or pickup-hours edit completed.
      await saveNow();
      const urlParams = new URLSearchParams(window.location.search);
      const currentDraftId = draftId ?? urlParams.get('draftId');
      if (!currentDraftId) {
        form.setError('root', { message: tDrafts('savingError') });
        return;
      }
      const res = await fetchWithRefresh(`/api/vendor/deals/drafts/${currentDraftId}/submit`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify(body),
        credentials: 'same-origin',
      });
      if (res.status === 400) {
        const data = (await res.json()) as {
          fieldErrors?: Record<string, string[]>;
          error?: string;
        };
        if (data.fieldErrors) {
          for (const [field, msgs] of Object.entries(data.fieldErrors)) {
            form.setError(field as keyof AddDealFormValues, { message: msgs[0] });
          }
        } else {
          form.setError('root', { message: data.error ?? tDrafts('savingError') });
        }
        return;
      }
      if (!res.ok) {
        const data = (await res.json()) as { error?: string };
        form.setError('root', { message: data.error ?? tDrafts('savingError') });
        return;
      }
      const okData = (await res.json()) as { ok: boolean; dealId?: string; id?: string };
      const newId = okData.dealId ?? okData.id ?? '';
      if (dealTypeCaps(values.dealType).hasShipping && newId) {
        await fetchWithRefresh(`/api/vendor/deals/${newId}/shipping-config`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
          body: JSON.stringify({
            preferredCarrier: values.pickupEnabled ? null : (values.preferredCarrier ?? null),
            shippingMode: values.shippingMode ?? 'free',
            shippingFlatAgorot:
              values.shippingFlatAgorot != null
                ? Math.round(values.shippingFlatAgorot * 100)
                : null,
            shippingFreeThresholdAgorot:
              values.shippingFreeThresholdAgorot != null
                ? Math.round(values.shippingFreeThresholdAgorot * 100)
                : null,
            pickupEnabled: values.pickupEnabled ?? false,
            pickupAddressId: values.pickupEnabled ? (values.pickupAddressId ?? null) : null,
          }),
          credentials: 'same-origin',
        });
      }
      window.location.assign(newId ? `/vendor/deals/${newId}` : successRedirect);
      return;
    }

    // Edit mode — PATCH active deal directly.
    if (isEditMode && dealId) {
      const res = await fetchWithRefresh(`/api/vendor/deals/${dealId}`, {
        method: 'PATCH',
        headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
        body: JSON.stringify(body),
        credentials: 'same-origin',
      });
      const data = (await res.json()) as {
        ok: boolean;
        dealId?: string;
        id?: string;
        fieldErrors?: Record<string, string[]>;
        error?: string;
      };
      if (res.status === 400 && data.fieldErrors) {
        for (const [field, msgs] of Object.entries(data.fieldErrors)) {
          form.setError(field as keyof AddDealFormValues, { message: msgs[0] });
        }
        return;
      }
      if (!data.ok) {
        form.setError('root', { message: data.error ?? tDrafts('savingError') });
        return;
      }
      if (dealTypeCaps(values.dealType).hasShipping && dealId) {
        await fetchWithRefresh(`/api/vendor/deals/${dealId}/shipping-config`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json', 'x-csrf-token': getCsrfToken() },
          body: JSON.stringify({
            preferredCarrier: values.pickupEnabled ? null : (values.preferredCarrier ?? null),
            shippingMode: values.shippingMode ?? 'free',
            shippingFlatAgorot:
              values.shippingFlatAgorot != null
                ? Math.round(values.shippingFlatAgorot * 100)
                : null,
            shippingFreeThresholdAgorot:
              values.shippingFreeThresholdAgorot != null
                ? Math.round(values.shippingFreeThresholdAgorot * 100)
                : null,
            pickupEnabled: values.pickupEnabled ?? false,
            pickupAddressId: values.pickupEnabled ? (values.pickupAddressId ?? null) : null,
          }),
          credentials: 'same-origin',
        });
      }
      return;
    }

    // Fallback to hook's own submit when no vendorId.
    hookOnSubmit();
  });

  const toggleStar = useCallback(async () => {
    if (starPending) return;
    setStarPending(true);
    const next = !starred;
    setStarred(next);
    try {
      let currentDraftId = draftId;
      if (!currentDraftId) {
        await saveNow();
        const urlParams = new URLSearchParams(window.location.search);
        currentDraftId = urlParams.get('draftId');
      }
      if (!currentDraftId) {
        setStarred(!next);
        return;
      }
      await fetchWithRefresh(`/api/vendor/deals/drafts/${currentDraftId}/star`, {
        method: 'POST',
        headers: { 'x-csrf-token': getCsrfToken() },
        credentials: 'same-origin',
      });
    } catch (err) {
      captureCaught(err, { scope: 'features.vendor-add-deal.AddDeal', severity: 'warning' });
      setStarred(!next);
    } finally {
      setStarPending(false);
    }
  }, [draftId, starred, starPending, saveNow, setStarred]);

  const onArchive = useCallback(async () => {
    if (!dealId || archivePending) return;
    setArchivePending(true);
    try {
      const res = await fetchWithRefresh(`/api/vendor/deals/${dealId}/archive`, {
        method: 'POST',
        headers: { 'x-csrf-token': getCsrfToken(), 'Content-Type': 'application/json' },
        credentials: 'same-origin',
      });
      if (res.ok) {
        window.location.href = '/vendor/deals';
      } else {
        setArchivePending(false);
      }
    } catch (err) {
      captureCaught(err, { scope: 'features.vendor-add-deal.AddDeal', severity: 'warning' });
      setArchivePending(false);
    }
  }, [dealId, archivePending]);

  const onSubmitForReview = useCallback(async () => {
    if (!dealId || submitPending) return;
    setSubmitPending(true);
    try {
      const res = await fetchWithRefresh(`/api/vendor/deals/${dealId}/submit`, {
        method: 'POST',
        headers: { 'x-csrf-token': getCsrfToken(), 'Content-Type': 'application/json' },
        credentials: 'same-origin',
      });
      if (res.ok) {
        window.location.href = '/vendor/deals?tab=pending';
      } else {
        const data = (await res.json()) as { error?: string };
        form.setError('root', { message: data.error ?? tDrafts('savingError') });
        setSubmitPending(false);
      }
    } catch (err) {
      captureCaught(err, { scope: 'features.vendor-add-deal.AddDeal', severity: 'warning' });
      setSubmitPending(false);
    }
  }, [dealId, submitPending, form, tDrafts]);

  return {
    handleSubmit,
    starPending,
    toggleStar,
    archivePending,
    onArchive,
    submitPending,
    onSubmitForReview,
  };
}
