/**
 * useAddDeal - react-hook-form + mutation for creating/editing a deal (FDS §5.4).
 */

'use client';

import { useState, useEffect, useMemo } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { shippingMode } from '@/lib/enums/shipping-mode';
import { carrier, MANUAL_CARRIER } from '@/lib/enums/carrier';
import { variantAxisKind } from '@/lib/enums/variant-axis-kind';
import type { DealType } from '@/components/ui/domain/DealCard';
import { getCsrfToken } from '@/lib/csrf';
import { captureCaught } from '@/lib/observability';
import { fetchWithRefresh } from '@/lib/api/refresh-on-401';
import { imageSetSchema } from '@/server/schemas/vendor';
import type { ImageSet } from '@/server/schemas/vendor';
import { discountedPrice, discountedPriceStr } from './discount';
import { dealTypeSchema } from '@/lib/deal-types/schema';
import { dealTypeCaps } from '@/lib/deal-types';
import { deliveryMode, type DeliveryMode } from '@/lib/enums/delivery-mode';
import { fillRule } from '@/lib/enums/fill-rule';
import { cancellationPolicy } from '@/lib/enums/cancellation-policy';
import { useT } from '@/lib/i18n/react';

export const MIN_DISCOUNT_PERCENT = 50;

export interface AddDealSchemaMessages {
  error_required: string;
  error_invalid_price: string;
  error_price_positive: string;
  error_enter_number: string;
  error_max_discount: string;
  error_time_format: string;
  error_required_pickup_hours: string;
  errorMinPrice: string;
  windowEndAfterStart: string;
  launchModePastError: string;
}

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

/** Convert a datetime-local value (e.g. "2026-05-04T14:46") to ISO 8601 with the current TZ offset.
 *  If already an ISO with offset/Z, pass through unchanged so re-saving a resumed draft does not
 *  double-suffix the offset (which produced strings like "...:00+00:00:00+07:00" → server 400). */
export function toIsoWithOffset(value: string | undefined): string | undefined {
  if (!value) return undefined;
  if (/Z$|[+-]\d{2}:\d{2}$/.test(value)) return value;
  const tzOffset = -new Date().getTimezoneOffset(); // minutes, positive = east
  const sign = tzOffset >= 0 ? '+' : '-';
  const absOffset = Math.abs(tzOffset);
  const offsetHH = String(Math.floor(absOffset / 60)).padStart(2, '0');
  const offsetMM = String(absOffset % 60).padStart(2, '0');
  const offsetStr = `${sign}${offsetHH}:${offsetMM}`;
  return `${value}:00${offsetStr}`;
}

// ─── Delivery options for PRODUCT ─────────────────────────────────────────────

export type DeliveryOption = DeliveryMode;

// ─── Form Schema ──────────────────────────────────────────────────────────────

export function buildAddDealSchema(msgs: AddDealSchemaMessages) {
  return z
    .object({
      dealType: dealTypeSchema,
      title: z.string().trim().min(1, msgs.error_required).max(120),
      description: z.string().trim().max(2000).optional(),
      categoryId: z.string().optional(),
      tagIds: z.array(z.string()),
      isVoucher: z.boolean(),
      imageSet: imageSetSchema.optional(),
      originalPrice: z
        .string()
        .trim()
        .regex(/^\d+(\.\d{1,2})?$/, msgs.error_invalid_price)
        .refine((v) => Number(v) > 0, msgs.error_price_positive),
      discountPercent: z
        .number({ error: msgs.error_enter_number })
        .int()
        .min(0)
        .max(99, msgs.error_max_discount),
      quantity: z.number({ error: msgs.error_enter_number }).int().min(1).max(10000),
      windowStart: z.string().optional(),
      windowEnd: z.string().optional(),
      pickupAddress: z.string().trim().max(300).optional(),
      pickupEnabled: z.boolean(),
      pickupAddressId: z.uuid().nullable().optional(),
      pickupStart: z
        .string()
        .trim()
        .regex(/^\d{2}:\d{2}$/, msgs.error_time_format)
        .optional()
        .or(z.literal('')),
      pickupEnd: z
        .string()
        .trim()
        .regex(/^\d{2}:\d{2}$/, msgs.error_time_format)
        .optional()
        .or(z.literal('')),
      delivery: deliveryMode.schema.optional(),
      specialInstructions: z.string().trim().max(1000).optional(),
      // GROUP specific
      groupFillRule: fillRule.schema.optional(),
      groupMinSize: z.number({ error: msgs.error_enter_number }).int().min(2).optional(),
      groupMaxSize: z.number({ error: msgs.error_enter_number }).int().min(2).optional(),
      groupPerCustomerLimit: z.number({ error: msgs.error_enter_number }).int().min(1).optional(),
      groupDeadline: z.string().optional(),
      groupCancellationPolicy: cancellationPolicy.schema.optional(),
      groupCancellationWindowHours: z
        .number({ error: msgs.error_enter_number })
        .int()
        .min(1)
        .optional(),
      groupTieredPricing: z.boolean().optional(),
      groupTiers: z
        .array(
          z.object({
            id: z.string().optional(),
            minParticipants: z.number().int().min(2),
            pricePerUnit: z.number().min(0),
          }),
        )
        .optional(),
      groupEarlyBird: z.boolean().optional(),
      groupEarlyBirdSlots: z.number({ error: msgs.error_enter_number }).int().min(1).optional(),
      groupEarlyBirdDiscountPercent: z
        .number({ error: msgs.error_enter_number })
        .int()
        .min(1)
        .max(50)
        .optional(),
      groupSocialSharing: z.boolean().optional(),
      groupSocialSharingReward: z.string().trim().max(500).optional(),
      groupBulkPickup: z.boolean().optional(),
      groupBulkPickupDetails: z.string().trim().max(1000).optional(),
      maxPerUser: z.number().int().min(1).max(1000).optional().nullable(),
      // ─── Variants / pricing mode ──────────────────────────────────────────
      variantsMode: z.enum(['single', 'variants']).optional(),
      variantsSingle: z
        .object({
          originalPrice: z.string().regex(/^\d+(\.\d{1,2})?$/),
          discountPercent: z.number().int().min(0).max(99),
          discountedPrice: z.string().regex(/^\d+(\.\d{1,2})?$/),
          quantityTotal: z.number().int().positive(),
        })
        .optional(),
      /** Quantity-discount tiers for single-SKU deals (mirrors variantsSkus[n].qtyTiers). */
      singleQtyTiers: z
        .array(
          z.object({
            id: z.string().optional(),
            minQty: z.number().int().min(2),
            discountPercent: z.number().int().min(1).max(100),
          }),
        )
        .max(5)
        .optional(),
      variantsAxes: z
        .array(
          z.object({
            axisOrder: z.number().int().min(0),
            kind: variantAxisKind.schema,
            nameHe: z.string().min(1).max(40),
            nameEn: z.string().min(1).max(40),
            options: z
              .array(
                z.object({
                  optionOrder: z.number().int().min(0),
                  valueCode: z.string().min(1).max(40),
                  labelHe: z.string().min(1).max(40),
                  labelEn: z.string().min(1).max(40),
                  slotStart: z.string().nullable().optional(),
                  slotEnd: z.string().nullable().optional(),
                  swatchHex: z
                    .string()
                    .regex(/^#[0-9a-f]{6}$/i)
                    .nullable()
                    .optional(),
                }),
              )
              .min(1),
          }),
        )
        .max(3)
        .optional(),
      variantsSkus: z
        .array(
          z.object({
            optionValueCodes: z.array(z.string()),
            originalPrice: z.string().regex(/^\d+(\.\d{1,2})?$/),
            discountPercent: z.number().int().min(0).max(99),
            discountedPrice: z.string().regex(/^\d+(\.\d{1,2})?$/),
            quantityTotal: z.number().int().nonnegative(),
            qtyTiers: z
              .array(
                z.object({
                  id: z.string().optional(),
                  minQty: z.number().int().min(2),
                  discountPercent: z.number().int().min(1).max(100),
                }),
              )
              .max(5)
              .optional(),
          }),
        )
        .optional(),
      // Shipping config (ITEM deals only)
      preferredCarrier: z
        // Preferred-carrier subset: excludes pickup only (no-carrier path). wolt_drive included (auto-dispatched via Wolt Drive).
        .enum(carrier.schema.extract([...MANUAL_CARRIER, 'wolt_drive']).options)
        .nullable()
        .optional(),
      // pickup handled via deliveryMode; pickup_only is pricing-path only
      shippingMode: shippingMode.schema.extract(['free', 'flat', 'free_over_threshold']).optional(),
      shippingFlatAgorot: z.number().int().min(0).optional(),
      shippingFreeThresholdAgorot: z.number().int().min(0).optional(),
    })
    .superRefine((val, ctx) => {
      if (val.windowStart && val.windowEnd) {
        const start = new Date(val.windowStart);
        const end = new Date(val.windowEnd);
        if (!Number.isNaN(start.getTime()) && !Number.isNaN(end.getTime()) && end <= start) {
          ctx.addIssue({
            path: ['windowEnd'],
            code: 'custom',
            message: msgs.windowEndAfterStart,
          });
        }
      }
      // Client mirrors server: windowStart must not be more than 5 min in the past.
      // (launchMode==='now' overrides windowStart at submit time — this guard only
      //  applies when the user has explicitly chosen a scheduled date.)
      if (val.windowStart) {
        const start = new Date(val.windowStart);
        const fiveMinAgo = Date.now() - 5 * 60 * 1000;
        if (!Number.isNaN(start.getTime()) && start.getTime() < fiveMinAgo) {
          ctx.addIssue({
            path: ['windowStart'],
            code: 'custom',
            message: msgs.launchModePastError,
          });
        }
      }
      // Pickup hours required for COUPON when delivery includes pickup
      // (PICKUP_ONLY or BOTH). Mirrors server `createDealBodySchema` gate.
      if (dealTypeCaps(val.dealType).requiresPickupHours && val.delivery !== 'DELIVERY') {
        if (!val.pickupStart) {
          ctx.addIssue({
            path: ['pickupStart'],
            code: 'custom',
            message: msgs.error_required_pickup_hours,
          });
        }
        if (!val.pickupEnd) {
          ctx.addIssue({
            path: ['pickupEnd'],
            code: 'custom',
            message: msgs.error_required_pickup_hours,
          });
        }
      }
      const discounted = discountedPrice(Number(val.originalPrice), val.discountPercent);
      if (discounted < 3) {
        ctx.addIssue({
          path: ['discountPercent'],
          code: 'custom',
          message: msgs.errorMinPrice,
        });
      }
    });
}

export type AddDealFormValues = z.infer<ReturnType<typeof buildAddDealSchema>>;

export interface UseAddDealOptions {
  dealId?: string;
  draftId?: string | null;
  saveNow?: () => Promise<void>;
  defaultValues?: Partial<AddDealFormValues>;
  isVeteran?: boolean;
  onSuccess?: (dealId: string) => void;
}

export function useAddDeal({
  dealId,
  draftId,
  saveNow,
  defaultValues,
  isVeteran = false,
  onSuccess,
}: UseAddDealOptions = {}) {
  const t = useT('vendor_add_deal');
  const [serverError, setServerError] = useState<string | null>(null);

  const schema = useMemo(
    () =>
      buildAddDealSchema({
        error_required: t('error_required'),
        error_invalid_price: t('error_invalid_price'),
        error_price_positive: t('error_price_positive'),
        error_enter_number: t('error_enter_number'),
        error_max_discount: t('error_max_discount'),
        error_time_format: t('error_time_format'),
        error_required_pickup_hours: t('error_required_pickup_hours'),
        errorMinPrice: t('error_min_price'),
        windowEndAfterStart: t('window_end_after_start'),
        launchModePastError: t('launch_mode_past_error'),
      }),
    [t],
  );

  // Stable defaults computed once at mount — stored in a ref to satisfy
  // react-hooks/purity (Date is impure; ref initializer runs outside render).
  const windowDefaults = useState(() => ({
    start: toLocalStr(new Date()),
    end: toLocalStr(new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)),
  }))[0];

  const form = useForm<AddDealFormValues>({
    resolver: zodResolver(schema),
    defaultValues: {
      dealType: 'COUPON',
      quantity: 10,
      discountPercent: 50,
      tagIds: [],
      isVoucher: false,
      windowStart: windowDefaults.start,
      windowEnd: windowDefaults.end,
      variantsMode: 'single',
      variantsAxes: [],
      variantsSkus: [],
      maxPerUser: null,
      preferredCarrier: null,
      shippingMode: 'free' as const,
      shippingFlatAgorot: 0,
      shippingFreeThresholdAgorot: 0,
      pickupEnabled: false,
      pickupAddressId: null,
      ...defaultValues,
    },
  });

  // In edit mode, fetch the existing deal and reset the form.
  useEffect(() => {
    if (!dealId) return;
    let cancelled = false;
    fetchWithRefresh(`/api/vendor/deals/${dealId}`)
      .then((r) => r.json() as Promise<{ ok: boolean; deal: Record<string, unknown> }>)
      .then(({ ok, deal }) => {
        if (!ok || cancelled || !deal) return;
        // Merge over current form values (which already include schema-required
        // defaults like tagIds:[], isVoucher:false). RHF's `reset(values)`
        // REPLACES state — passing only the fields we know about would leave
        // required fields like `tagIds` / `isVoucher` undefined and silently
        // fail client-side zod, swallowing submit.
        const dealTagIds = Array.isArray(deal.tagIds)
          ? (deal.tagIds as unknown[]).filter((x): x is string => typeof x === 'string')
          : undefined;
        const next: Partial<AddDealFormValues> = {
          ...form.getValues(),
          dealType: (deal.dealType as AddDealFormValues['dealType']) ?? 'COUPON',
          title: (deal.title as string) ?? '',
          description: (deal.description as string) ?? '',
          categoryId: typeof deal.categoryId === 'string' ? (deal.categoryId as string) : undefined,
          tagIds: dealTagIds ?? [],
          isVoucher: typeof deal.isVoucher === 'boolean' ? (deal.isVoucher as boolean) : false,
          imageSet: deal.imageSet !== undefined ? (deal.imageSet as ImageSet) : undefined,
          originalPrice: deal.originalPrice !== undefined ? String(deal.originalPrice) : '',
          discountPercent: typeof deal.discountPercent === 'number' ? deal.discountPercent : 50,
          quantity: typeof deal.quantityTotal === 'number' ? deal.quantityTotal : 10,
          windowStart:
            typeof deal.windowStart === 'string' ? deal.windowStart?.slice(0, 16) : undefined,
          windowEnd: typeof deal.windowEnd === 'string' ? deal.windowEnd?.slice(0, 16) : undefined,
          pickupAddress: (deal.pickupAddress as string) ?? '',
          pickupEnabled: false,
          pickupAddressId: null,
          pickupStart:
            typeof deal.pickupStart === 'string' ? deal.pickupStart.slice(0, 5) : undefined,
          pickupEnd: typeof deal.pickupEnd === 'string' ? deal.pickupEnd.slice(0, 5) : undefined,
          delivery: (deal.delivery as AddDealFormValues['delivery'] | undefined) ?? undefined,
          specialInstructions: (deal.specialInstructions as string) ?? undefined,
          maxPerUser: typeof deal.maxPerUser === 'number' ? (deal.maxPerUser as number) : null,
        };

        // ── Hydrate variants/SKU/tier data ────────────────────────────────
        // GET /api/vendor/deals/[id] now returns deal.axes + deal.skus (with qtyTiers).
        // Mode is derived: axes.length > 0 → 'variants', else → 'single'.
        const rawAxes = Array.isArray(deal.axes) ? deal.axes : [];
        const rawSkus = Array.isArray(deal.skus) ? deal.skus : [];

        if (rawAxes.length > 0) {
          // Variants mode
          next.variantsMode = 'variants';
          next.variantsAxes = rawAxes as AddDealFormValues['variantsAxes'];
          next.variantsSkus = (rawSkus as Array<Record<string, unknown>>).map((s) => ({
            optionValueCodes: Array.isArray(s.optionValueCodes)
              ? (s.optionValueCodes as string[])
              : [],
            originalPrice: s.originalPrice !== undefined ? String(s.originalPrice) : '',
            discountPercent: typeof s.discountPercent === 'number' ? s.discountPercent : 50,
            discountedPrice: s.discountedPrice !== undefined ? String(s.discountedPrice) : '',
            quantityTotal: typeof s.quantityTotal === 'number' ? s.quantityTotal : 0,
            qtyTiers: Array.isArray(s.qtyTiers)
              ? (s.qtyTiers as Array<{ minQty: number; discountPercent: number }>).map((t) => ({
                  id: crypto.randomUUID(),
                  minQty: t.minQty,
                  discountPercent: t.discountPercent,
                }))
              : [],
          }));
        } else if (rawSkus.length > 0) {
          // Single mode — first (and only) SKU holds pricing + tiers
          const singleSku = rawSkus[0] as Record<string, unknown>;
          next.variantsMode = 'single';
          next.originalPrice =
            singleSku?.originalPrice !== undefined ? String(singleSku.originalPrice) : '';
          next.discountPercent =
            typeof singleSku?.discountPercent === 'number' ? singleSku.discountPercent : 50;
          next.quantity =
            typeof singleSku?.quantityTotal === 'number' ? singleSku.quantityTotal : 10;
          next.singleQtyTiers = Array.isArray(singleSku?.qtyTiers)
            ? (singleSku.qtyTiers as Array<{ minQty: number; discountPercent: number }>).map(
                (t) => ({
                  id: crypto.randomUUID(),
                  minQty: t.minQty,
                  discountPercent: t.discountPercent,
                }),
              )
            : [];
        }

        form.reset(next as AddDealFormValues);
      })
      .catch((err) => {
        captureCaught(err, { scope: 'features.vendor-add-deal.useAddDeal', severity: 'info' });
        /* non-fatal - user can re-enter values */
      });
    return () => {
      cancelled = true;
    };
  }, [dealId, form]);

  // `useWatch` is compiler-memoizable (unlike `form.watch()` which returns a
  // function that react-hooks/incompatible-library can't safely memoize).
  const dealType = useWatch({ control: form.control, name: 'dealType' }) as DealType;
  const originalPrice = useWatch({ control: form.control, name: 'originalPrice' });
  const discountPercent = useWatch({ control: form.control, name: 'discountPercent' });

  const calculatedPrice =
    originalPrice && discountPercent
      ? discountedPriceStr(Number(originalPrice), discountPercent)
      : null;

  async function onSubmit(values: AddDealFormValues) {
    setServerError(null);
    try {
      const {
        quantity: _quantity,
        maxPerUser: _maxPerUser,
        variantsMode,
        variantsSingle,
        variantsAxes,
        variantsSkus,
        singleQtyTiers,
        // GROUP-prefixed fields — remapped to API names below
        groupFillRule,
        groupMinSize,
        groupMaxSize,
        groupPerCustomerLimit,
        groupDeadline,
        groupCancellationPolicy,
        groupCancellationWindowHours,
        groupTieredPricing,
        groupTiers,
        groupEarlyBird,
        groupEarlyBirdSlots,
        groupEarlyBirdDiscountPercent,
        groupSocialSharing,
        groupSocialSharingReward,
        groupBulkPickup,
        groupBulkPickupDetails,
        ...restValues
      } = values;

      // Remap group-prefixed form fields to the API's expected unprefixed names.
      const groupFields =
        values.dealType === 'GROUP'
          ? {
              fillRule: groupFillRule,
              minGroupSize: groupMinSize,
              maxGroupSize: groupMaxSize,
              perCustomerLimit: groupPerCustomerLimit,
              deadline: toIsoWithOffset(groupDeadline),
              cancellationPolicy: groupCancellationPolicy,
              cancellationWindowHours: groupCancellationWindowHours,
              tieredPricingEnabled: groupTieredPricing,
              tiers: groupTiers,
              earlyBirdEnabled: groupEarlyBird,
              earlyBirdSlots: groupEarlyBirdSlots,
              earlyBirdDiscountPercent: groupEarlyBirdDiscountPercent,
              socialSharingEnabled: groupSocialSharing,
              socialSharingReward: groupSocialSharingReward,
              bulkPickupEnabled: groupBulkPickup,
              bulkPickupDetails: groupBulkPickupDetails,
            }
          : {};

      // Build nested variants block for the API.
      // Single mode: send pricing inline on body (legacy scalar path) + variants.mode.
      // Variants mode: send axes + skus under body.variants.
      const variantsBlock =
        variantsMode === 'variants'
          ? {
              mode: 'variants' as const,
              variants: {
                axes: variantsAxes ?? [],
                skus: variantsSkus ?? [],
              },
            }
          : {
              mode: 'single' as const,
              single: {
                ...(variantsSingle ?? {
                  originalPrice: restValues.originalPrice ?? '',
                  discountPercent: Number(restValues.discountPercent ?? 50),
                  discountedPrice: calculatedPrice ?? '0',
                  quantityTotal: _quantity ?? 0,
                }),
                qtyTiers: singleQtyTiers ?? [],
              },
            };

      const body = {
        ...restValues,
        ...groupFields,
        discountedPrice: calculatedPrice ?? '0',
        quantityTotal: _quantity,
        maxPerUser: _maxPerUser ?? undefined,
        windowStart: toIsoWithOffset(values.windowStart),
        windowEnd: toIsoWithOffset(values.windowEnd),
        variants: variantsBlock,
      };

      // Edit mode — PATCH active deal directly. Bypasses draft flow entirely
      // (drafts only make sense for new deals; active deal is source of truth).
      if (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) {
          setServerError(data.error ?? t('error_update_failed'));
          return;
        }
        onSuccess?.(data.dealId ?? data.id ?? dealId);
        return;
      }

      // Draft-based submit flow (new deals)
      if (draftId !== undefined && draftId !== null) {
        // Ensure draft is saved first if we have a saveNow
        let currentDraftId = draftId;
        if (!currentDraftId && saveNow) {
          await saveNow();
          // draftId updated via state — read from URL as fallback
          const urlParams = new URLSearchParams(window.location.search);
          currentDraftId = urlParams.get('draftId') ?? '';
        }
        if (!currentDraftId) {
          setServerError(t('error_draft_save_failed'));
          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 {
            ok: boolean;
            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 {
            setServerError(data.error ?? t('error_submission_failed'));
          }
          return;
        }
        if (!res.ok) {
          const data = (await res.json()) as { error?: string };
          setServerError(data.error ?? t('error_submission_failed'));
          return;
        }
        const data = (await res.json()) as { ok: boolean; dealId?: string; id?: string };
        const newId = data.dealId ?? data.id ?? '';
        onSuccess?.(newId);
        return;
      }

      // Direct deal create/edit flow (edit mode without draft)
      const url = dealId ? `/api/vendor/deals/${dealId}` : '/api/vendor/deals';
      const method = dealId ? 'PATCH' : 'POST';

      const res = await fetchWithRefresh(url, {
        method,
        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;
        error?: string;
      };
      if (!data.ok) {
        setServerError(data.error ?? t('error_submission_failed'));
        return;
      }
      const newId = data.dealId ?? data.id ?? dealId ?? '';
      onSuccess?.(newId);
    } catch (err) {
      captureCaught(err, { scope: 'features.vendor-add-deal.useAddDeal', severity: 'warning' });
      setServerError(t('error_network'));
    }
  }

  return {
    form,
    dealType,
    calculatedPrice,
    serverError,
    onSubmit: form.handleSubmit(onSubmit),
    isVeteran,
  };
}
