"use client";

import { useId, useState, type ReactNode } from "react";
import { Button } from "@/components/Button";
import { CampaignFieldLabel } from "@/components/dashboard/CampaignFieldLabel";
import { CampaignGenderPicker } from "@/components/dashboard/CampaignGenderPicker";
import { CampaignLocationPicker } from "@/components/dashboard/CampaignLocationPicker";
import { SocialProviderIcon } from "@/components/dashboard/SocialProviderIcon";
import { fieldClassName, fieldInvalidClassName, textareaClassName } from "@/components/ui/field-styles";
import { cn } from "@/lib/cn";
import { CAMPAIGN_FIELD_REQUIREMENTS } from "@/lib/campaign-field-labels";
import { DEFAULT_CAMPAIGN_CURRENCY } from "@/lib/campaign-wizard";
import {
  CAMPAIGN_AUDIENCE_AGE_RANGES,
  CAMPAIGN_AUDIENCE_GENDERS,
  CAMPAIGN_DELIVERABLE_TYPES,
  CAMPAIGN_PLATFORMS,
  deliverableHasExtraDetails,
  deliverableTypePlatform,
  deliverableTypesForPlatform,
  isCampaignAudienceAgeRange,
  isCampaignAudienceGender,
  majorToMinorAmount,
  minorToMajorInput,
  normalizeCampaignAudienceAgeRanges,
  normalizeCampaignAudienceGenders,
  supportedDeliverablesFrom,
  supportedPlatformsFrom,
} from "@/lib/campaigns";
import { CREATOR_NICHE_OPTIONS, isCreatorNicheValue } from "@/lib/creator-personal-info";
import { socialProviderLabel } from "@/lib/social-providers";
import type {
  Campaign,
  CampaignAudienceAgeRange,
  CampaignAudienceGender,
  CampaignAudienceLocation,
  CampaignDeliverableType,
  CampaignStatus,
  CampaignWritePayload,
} from "@/types/campaign";
import type { SocialProvider } from "@/types/social-account";
import type { ValidationErrors } from "@/lib/api";

export type CampaignFormValues = {
  name: string;
  description: string;
  platforms: SocialProvider[];
  locations: CampaignAudienceLocation[];
  ageRanges: CampaignAudienceAgeRange[];
  genders: CampaignAudienceGender[];
  categories: string[];
  deliverables: {
    type: CampaignDeliverableType;
    quantity: string;
    description: string;
    creator_instructions: string;
    reference_url: string;
  }[];
  budgetMajor: string;
  startDate: string;
  endDate: string;
  status: CampaignStatus;
};

function allowedDeliverableTypes(platforms: SocialProvider[]): CampaignDeliverableType[] {
  if (platforms.length === 0) {
    return CAMPAIGN_DELIVERABLE_TYPES.map((option) => option.value);
  }

  const seen = new Set<CampaignDeliverableType>();
  const types: CampaignDeliverableType[] = [];
  for (const platform of platforms) {
    for (const type of deliverableTypesForPlatform(platform)) {
      if (!seen.has(type)) {
        seen.add(type);
        types.push(type);
      }
    }
  }
  return types;
}

function emptyDeliverable(
  platforms: SocialProvider[] = ["instagram"],
): CampaignFormValues["deliverables"][number] {
  const types = allowedDeliverableTypes(platforms);
  return {
    type: types[0] ?? "instagram_post",
    quantity: "1",
    description: "",
    creator_instructions: "",
    reference_url: "",
  };
}

export function campaignToFormValues(campaign: Campaign): CampaignFormValues {
  const audience = campaign.target_audience;
  const platforms = supportedPlatformsFrom(campaign.platforms);
  const deliverables = supportedDeliverablesFrom(campaign.deliverables);

  return {
    name: campaign.name,
    description: campaign.description ?? "",
    platforms,
    locations: audience?.locations ? [...audience.locations] : [],
    ageRanges: normalizeCampaignAudienceAgeRanges(audience?.age_ranges ?? []),
    genders: normalizeCampaignAudienceGenders(audience?.genders ?? []),
    categories: (audience?.interests ?? []).filter(isCreatorNicheValue),
    deliverables:
      deliverables.length > 0
        ? deliverables.map((item) => ({
            type: item.type,
            quantity: String(item.quantity),
            description: item.description ?? "",
            creator_instructions: item.creator_instructions ?? "",
            reference_url: item.reference_url ?? "",
          }))
        : [emptyDeliverable(platforms)],
    budgetMajor: minorToMajorInput(campaign.budget_amount),
    startDate: campaign.start_date,
    endDate: campaign.end_date,
    status: campaign.status,
  };
}

export function defaultCampaignFormValues(status: CampaignStatus = "draft"): CampaignFormValues {
  const start = new Date();
  start.setDate(start.getDate() + 7);
  const end = new Date();
  end.setDate(end.getDate() + 21);

  return {
    name: "",
    description: "",
    platforms: ["instagram"],
    locations: [],
    ageRanges: [],
    genders: [],
    categories: [],
    deliverables: [emptyDeliverable(["instagram"])],
    budgetMajor: "",
    startDate: start.toISOString().slice(0, 10),
    endDate: end.toISOString().slice(0, 10),
    status,
  };
}

function firstFieldError(errors: ValidationErrors, key: string): string | undefined {
  const messages = errors[key];
  return messages?.[0];
}

function FormSection({ title, children }: { title: string; children: ReactNode }) {
  return (
    <section className="border-t border-line pt-4 first:border-t-0 first:pt-0">
      <h2 className="text-[0.875rem] font-semibold text-primary">{title}</h2>
      <div className="mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2">{children}</div>
    </section>
  );
}

function FieldError({ id, message }: { id: string; message?: string }) {
  if (!message) return null;
  return (
    <p id={id} className="mt-1 text-[0.75rem] text-accent" role="alert">
      {message}
    </p>
  );
}

function TextField({
  id,
  label,
  required = false,
  value,
  onChange,
  error,
  type = "text",
  disabled,
  span,
  hint,
  inputMode,
  min,
  max,
}: {
  id: string;
  label: string;
  required?: boolean;
  value: string;
  onChange: (value: string) => void;
  error?: string;
  type?: "text" | "date" | "number";
  disabled?: boolean;
  span?: boolean;
  hint?: string;
  inputMode?: "decimal" | "numeric";
  min?: number | string;
  max?: number | string;
}) {
  const errorId = `${id}-error`;
  return (
    <div className={span ? "sm:col-span-2" : undefined}>
      <CampaignFieldLabel htmlFor={id} label={label} required={required} />
      <input
        id={id}
        type={type}
        value={value}
        disabled={disabled}
        inputMode={inputMode}
        min={min}
        max={max}
        required={required}
        aria-required={required || undefined}
        aria-invalid={error ? true : undefined}
        aria-describedby={error ? errorId : undefined}
        className={cn(fieldClassName, error && fieldInvalidClassName)}
        onChange={(event) => onChange(event.target.value)}
      />
      {hint ? <p className="mt-1 text-[0.75rem] text-ink-40">{hint}</p> : null}
      <FieldError id={errorId} message={error} />
    </div>
  );
}

function TextAreaField({
  id,
  label,
  required = false,
  value,
  onChange,
  error,
  disabled,
  rows = 4,
}: {
  id: string;
  label: string;
  required?: boolean;
  value: string;
  onChange: (value: string) => void;
  error?: string;
  disabled?: boolean;
  rows?: number;
}) {
  const errorId = `${id}-error`;
  return (
    <div className="sm:col-span-2">
      <CampaignFieldLabel htmlFor={id} label={label} required={required} />
      <textarea
        id={id}
        value={value}
        disabled={disabled}
        rows={rows}
        required={required}
        aria-required={required || undefined}
        aria-invalid={error ? true : undefined}
        aria-describedby={error ? errorId : undefined}
        className={cn(textareaClassName, error && fieldInvalidClassName)}
        onChange={(event) => onChange(event.target.value)}
      />
      <FieldError id={errorId} message={error} />
    </div>
  );
}

export function buildCampaignPayload(
  values: CampaignFormValues,
  status: CampaignStatus,
): { payload: CampaignWritePayload } | { errors: ValidationErrors } {
  const errors: ValidationErrors = {};

  const name = values.name.trim();
  if (!name) {
    errors.name = ["Campaign name is required."];
  } else if (name.length > 120) {
    errors.name = ["Campaign name must be 120 characters or fewer."];
  }

  const description = values.description.trim();
  if (description.length > 5000) {
    errors.description = ["Description must be 5000 characters or fewer."];
  }

  if (values.platforms.length === 0) {
    errors.platforms = ["Select at least one network."];
  }

  const budgetAmount = majorToMinorAmount(values.budgetMajor, DEFAULT_CAMPAIGN_CURRENCY);
  if (budgetAmount === null) {
    errors.budget_amount = ["Enter a valid budget amount greater than zero."];
  }

  if (!values.startDate) {
    errors.start_date = ["Start date is required."];
  }
  if (!values.endDate) {
    errors.end_date = ["End date is required."];
  } else if (values.startDate && values.endDate < values.startDate) {
    errors.end_date = ["End date must be on or after the start date."];
  }

  if (values.locations.length > 20) {
    errors["target_audience.locations"] = ["Add at most 20 locations."];
  }

  for (const [index, location] of values.locations.entries()) {
    if (!location.display_name.trim()) {
      errors[`target_audience.locations.${index}.display_name`] = [
        "Location display name is required.",
      ];
    } else if (location.display_name.trim().length > 255) {
      errors[`target_audience.locations.${index}.display_name`] = [
        "Location display name must be 255 characters or fewer.",
      ];
    }
  }

  if (values.categories.length > 20) {
    errors["target_audience.interests"] = ["Add at most 20 categories."];
  } else if (values.categories.some((item) => !isCreatorNicheValue(item))) {
    errors["target_audience.interests"] = ["Select categories from the creator category list."];
  }

  const deliverables: CampaignWritePayload["deliverables"] = [];
  const selectedPlatforms = new Set(values.platforms);
  if (values.deliverables.length === 0) {
    errors.deliverables = ["Add at least one deliverable."];
  } else {
    values.deliverables.forEach((item, index) => {
      if (!item.type) {
        errors[`deliverables.${index}.type`] = ["Deliverable type is required."];
      } else if (
        selectedPlatforms.size > 0 &&
        !selectedPlatforms.has(deliverableTypePlatform(item.type))
      ) {
        errors[`deliverables.${index}.type`] = ["Deliverable type must match a selected network."];
      }

      const quantityRaw = item.quantity.trim();
      const quantity = Number.parseInt(quantityRaw, 10);
      if (!quantityRaw) {
        errors[`deliverables.${index}.quantity`] = ["Quantity is required."];
      } else if (!Number.isInteger(quantity) || quantity < 1 || quantity > 100) {
        errors[`deliverables.${index}.quantity`] = ["Quantity must be between 1 and 100."];
      }

      if (item.description.trim().length > 500) {
        errors[`deliverables.${index}.description`] = ["Description must be 500 characters or fewer."];
      }
      if (item.creator_instructions.trim().length > 2000) {
        errors[`deliverables.${index}.creator_instructions`] = [
          "Creator instructions must be 2000 characters or fewer.",
        ];
      }

      const referenceUrl = item.reference_url.trim();
      if (referenceUrl) {
        if (referenceUrl.length > 2048) {
          errors[`deliverables.${index}.reference_url`] = [
            "Reference URL must be 2048 characters or fewer.",
          ];
        } else {
          try {
            const url = new URL(referenceUrl);
            if (url.protocol !== "http:" && url.protocol !== "https:") {
              errors[`deliverables.${index}.reference_url`] = ["Enter a valid URL."];
            }
          } catch {
            errors[`deliverables.${index}.reference_url`] = ["Enter a valid URL."];
          }
        }
      }

      if (
        !errors[`deliverables.${index}.quantity`] &&
        !errors[`deliverables.${index}.type`] &&
        item.type
      ) {
        deliverables.push({
          type: item.type,
          quantity,
          description: item.description.trim() || null,
          creator_instructions: item.creator_instructions.trim() || null,
          reference_url: referenceUrl || null,
        });
      }
    });
  }

  if (values.ageRanges.length > CAMPAIGN_AUDIENCE_AGE_RANGES.length) {
    errors["target_audience.age_ranges"] = ["Select fewer age groups."];
  } else if (values.ageRanges.some((item) => !isCampaignAudienceAgeRange(item))) {
    errors["target_audience.age_ranges"] = ["Select age groups from the available list."];
  }

  if (values.genders.length > CAMPAIGN_AUDIENCE_GENDERS.length) {
    errors["target_audience.genders"] = ["Select fewer gender options."];
  } else if (values.genders.some((item) => !isCampaignAudienceGender(item))) {
    errors["target_audience.genders"] = ["Select genders from the available list."];
  }

  if (Object.keys(errors).length > 0) {
    return { errors };
  }

  return {
    payload: {
      name,
      description: description || null,
      status,
      budget_amount: budgetAmount as number,
      currency: DEFAULT_CAMPAIGN_CURRENCY,
      start_date: values.startDate,
      end_date: values.endDate,
      platforms: values.platforms,
      target_audience: {
        locations: values.locations.map((location) => ({
          place_id: location.place_id,
          display_name: location.display_name.trim(),
          country: location.country,
          region: location.region,
          city: location.city,
        })),
        age_ranges: normalizeCampaignAudienceAgeRanges(values.ageRanges),
        genders: normalizeCampaignAudienceGenders(values.genders),
        interests: [...values.categories],
      },
      deliverables,
    },
  };
}

export function BrandCampaignForm({
  initialValues,
  mode,
  fieldErrors,
  busyAction,
  onSubmit,
  onCancel,
}: {
  initialValues: CampaignFormValues;
  mode: "create" | "edit";
  fieldErrors: ValidationErrors;
  busyAction: "draft" | "active" | "save" | null;
  onSubmit: (values: CampaignFormValues, status: CampaignStatus) => void;
  onCancel?: () => void;
}) {
  const formId = useId();
  const [values, setValues] = useState<CampaignFormValues>(initialValues);
  const [instructionsOpenIndexes, setInstructionsOpenIndexes] = useState<Set<number>>(() => {
    const open = new Set<number>();
    initialValues.deliverables.forEach((item, index) => {
      if (deliverableHasExtraDetails(item)) {
        open.add(index);
      }
    });
    return open;
  });
  const disabled = busyAction !== null;
  const deliverableTypeOptions = allowedDeliverableTypes(values.platforms);
  const networksLabelId = `${formId}-networks-label`;
  const categoryLabelId = `${formId}-category-label`;
  const ageLabelId = `${formId}-age-label`;
  const ageHintId = `${formId}-age-hint`;
  const ageErrorId = `${formId}-age-error`;
  const ageError = firstFieldError(fieldErrors, "target_audience.age_ranges");

  function update<K extends keyof CampaignFormValues>(key: K, value: CampaignFormValues[K]) {
    setValues((current) => ({ ...current, [key]: value }));
  }

  function togglePlatform(platform: SocialProvider) {
    setValues((current) => {
      const exists = current.platforms.includes(platform);
      return {
        ...current,
        platforms: exists
          ? current.platforms.filter((item) => item !== platform)
          : [...current.platforms, platform],
      };
    });
  }

  function toggleCategory(value: string) {
    setValues((current) => {
      const exists = current.categories.includes(value);
      return {
        ...current,
        categories: exists
          ? current.categories.filter((item) => item !== value)
          : [...current.categories, value],
      };
    });
  }

  function toggleAgeRange(value: CampaignAudienceAgeRange) {
    setValues((current) => {
      const exists = current.ageRanges.includes(value);
      return {
        ...current,
        ageRanges: exists
          ? current.ageRanges.filter((item) => item !== value)
          : [...current.ageRanges, value],
      };
    });
  }

  function updateDeliverable(
    index: number,
    patch: Partial<CampaignFormValues["deliverables"][number]>,
  ) {
    setValues((current) => ({
      ...current,
      deliverables: current.deliverables.map((item, itemIndex) =>
        itemIndex === index ? { ...item, ...patch } : item,
      ),
    }));
  }

  function toggleInstructions(index: number) {
    setInstructionsOpenIndexes((current) => {
      const next = new Set(current);
      if (next.has(index)) next.delete(index);
      else next.add(index);
      return next;
    });
  }

  return (
    <form
      id={formId}
      className="space-y-5"
      noValidate
      onSubmit={(event) => {
        event.preventDefault();
      }}
    >
      <FormSection title="Basic information">
        <TextField
          id={`${formId}-name`}
          label={CAMPAIGN_FIELD_REQUIREMENTS.name.label}
          required={CAMPAIGN_FIELD_REQUIREMENTS.name.required}
          value={values.name}
          disabled={disabled}
          error={firstFieldError(fieldErrors, "name")}
          onChange={(value) => update("name", value)}
          span
        />
        <TextAreaField
          id={`${formId}-description`}
          label={CAMPAIGN_FIELD_REQUIREMENTS.description.label}
          required={CAMPAIGN_FIELD_REQUIREMENTS.description.required}
          value={values.description}
          disabled={disabled}
          error={firstFieldError(fieldErrors, "description")}
          onChange={(value) => update("description", value)}
        />
      </FormSection>

      <FormSection title="Campaign details">
        <div
          className="sm:col-span-2"
          role="group"
          aria-labelledby={networksLabelId}
          aria-required={CAMPAIGN_FIELD_REQUIREMENTS.networks.required || undefined}
        >
          <CampaignFieldLabel
            as="p"
            id={networksLabelId}
            label={CAMPAIGN_FIELD_REQUIREMENTS.networks.label}
            required={CAMPAIGN_FIELD_REQUIREMENTS.networks.required}
            className="mb-1.5"
          />
          <div className="grid grid-cols-2 gap-2 sm:grid-cols-3 md:grid-cols-5">
            {CAMPAIGN_PLATFORMS.map((platform) => {
              const selected = values.platforms.includes(platform);
              return (
                <button
                  key={platform}
                  type="button"
                  disabled={disabled}
                  aria-pressed={selected}
                  className={cn(
                    "inline-flex items-center gap-2 rounded-pv border px-2.5 py-2 text-left text-[0.8125rem] font-medium transition focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
                    selected
                      ? "border-primary bg-bg text-primary"
                      : "border-line bg-surface text-ink-60 hover:border-primary/40",
                    disabled && "cursor-not-allowed opacity-70",
                  )}
                  onClick={() => togglePlatform(platform)}
                >
                  <SocialProviderIcon provider={platform} className="size-4" />
                  <span>{socialProviderLabel(platform)}</span>
                </button>
              );
            })}
          </div>
          <FieldError id={`${formId}-platforms-error`} message={firstFieldError(fieldErrors, "platforms")} />
        </div>

        <CampaignLocationPicker
          selected={values.locations}
          disabled={disabled}
          error={
            firstFieldError(fieldErrors, "target_audience.locations") ||
            firstFieldError(fieldErrors, "target_audience.location")
          }
          onChange={(locations) => update("locations", locations)}
        />
        <CampaignGenderPicker
          selected={values.genders}
          disabled={disabled}
          error={firstFieldError(fieldErrors, "target_audience.genders")}
          onChange={(genders) => update("genders", genders)}
        />
        <div
          className="sm:col-span-2"
          role="group"
          aria-labelledby={ageLabelId}
          aria-describedby={ageError ? `${ageHintId} ${ageErrorId}` : ageHintId}
        >
          <CampaignFieldLabel
            as="p"
            id={ageLabelId}
            label={CAMPAIGN_FIELD_REQUIREMENTS.audienceAge.label}
            required={CAMPAIGN_FIELD_REQUIREMENTS.audienceAge.required}
            className="mb-1.5"
          />
          <p id={ageHintId} className="mb-2 text-[0.75rem] text-ink-40">
            Select the age groups you want to reach.
          </p>
          <div className="flex flex-wrap gap-1.5">
            {CAMPAIGN_AUDIENCE_AGE_RANGES.map((option) => {
              const selected = values.ageRanges.includes(option.value);
              const checkboxId = `${formId}-age-${option.value}`;
              return (
                <label
                  key={option.value}
                  htmlFor={checkboxId}
                  className={cn(
                    "inline-flex cursor-pointer items-center gap-2 rounded-pv border px-2.5 py-1.5 text-[0.8125rem] font-medium transition focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-accent",
                    selected
                      ? "border-primary bg-bg text-primary"
                      : "border-line bg-surface text-ink-60 hover:border-primary/40",
                    disabled && "cursor-not-allowed opacity-70",
                  )}
                >
                  <input
                    id={checkboxId}
                    type="checkbox"
                    className="size-3.5 accent-primary"
                    checked={selected}
                    disabled={disabled}
                    onChange={() => toggleAgeRange(option.value)}
                  />
                  <span>{option.label}</span>
                </label>
              );
            })}
          </div>
          <FieldError id={ageErrorId} message={ageError} />
        </div>
        <div
          className="sm:col-span-2"
          role="group"
          aria-labelledby={categoryLabelId}
        >
          <CampaignFieldLabel
            as="p"
            id={categoryLabelId}
            label={CAMPAIGN_FIELD_REQUIREMENTS.category.label}
            required={CAMPAIGN_FIELD_REQUIREMENTS.category.required}
            className="mb-1.5"
          />
          <p className="mb-2 text-[0.75rem] text-ink-40">
            Same categories creators use on their profiles.
          </p>
          <div className="flex flex-wrap gap-1.5">
            {CREATOR_NICHE_OPTIONS.map((option) => {
              const selected = values.categories.includes(option.value);
              return (
                <button
                  key={option.value}
                  type="button"
                  disabled={disabled}
                  aria-pressed={selected}
                  className={cn(
                    "rounded-pv border px-2.5 py-1.5 text-[0.8125rem] font-medium transition focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent",
                    selected
                      ? "border-primary bg-bg text-primary"
                      : "border-line bg-surface text-ink-60 hover:border-primary/40",
                    disabled && "cursor-not-allowed opacity-70",
                  )}
                  onClick={() => toggleCategory(option.value)}
                >
                  {option.label}
                </button>
              );
            })}
          </div>
          <FieldError
            id={`${formId}-categories-error`}
            message={firstFieldError(fieldErrors, "target_audience.interests")}
          />
        </div>
      </FormSection>

      <section className="border-t border-line pt-4">
        <div className="flex items-center justify-between gap-2">
          <h2 className="text-[0.875rem] font-semibold text-primary">Deliverables</h2>
          <Button
            type="button"
            variant="secondary"
            size="sm"
            disabled={disabled || values.deliverables.length >= 20}
            onClick={() =>
              setValues((current) => ({
                ...current,
                deliverables: [...current.deliverables, emptyDeliverable(current.platforms)],
              }))
            }
          >
            Add deliverable
          </Button>
        </div>
        <FieldError id={`${formId}-deliverables-error`} message={firstFieldError(fieldErrors, "deliverables")} />
        <div className="mt-3 space-y-3">
          {values.deliverables.map((item, index) => {
            const typeOptions =
              deliverableTypeOptions.some((type) => type === item.type) || deliverableTypeOptions.length === 0
                ? deliverableTypeOptions
                : [...deliverableTypeOptions, item.type];
            const instructionsOpen = instructionsOpenIndexes.has(index);
            const hasInstructions = deliverableHasExtraDetails(item);
            const typeField = CAMPAIGN_FIELD_REQUIREMENTS.deliverableTypeShort;
            const qtyField = CAMPAIGN_FIELD_REQUIREMENTS.quantityShort;
            const descField = CAMPAIGN_FIELD_REQUIREMENTS.deliverableDescription;
            const instructionsField = CAMPAIGN_FIELD_REQUIREMENTS.creatorInstructions;
            const referenceField = CAMPAIGN_FIELD_REQUIREMENTS.referenceUrl;

            return (
              <div
                key={`${formId}-deliverable-${index}`}
                className="grid grid-cols-1 gap-3 rounded-pv border border-line bg-surface p-3 sm:grid-cols-12"
              >
                <div className="sm:col-span-4">
                  <CampaignFieldLabel
                    htmlFor={`${formId}-deliverable-type-${index}`}
                    label={typeField.label}
                    required={typeField.required}
                  />
                  <select
                    id={`${formId}-deliverable-type-${index}`}
                    value={item.type}
                    disabled={disabled}
                    required={typeField.required}
                    aria-required={typeField.required || undefined}
                    aria-invalid={
                      firstFieldError(fieldErrors, `deliverables.${index}.type`) ? true : undefined
                    }
                    className={cn(
                      fieldClassName,
                      firstFieldError(fieldErrors, `deliverables.${index}.type`) && fieldInvalidClassName,
                    )}
                    onChange={(event) =>
                      updateDeliverable(index, { type: event.target.value as CampaignDeliverableType })
                    }
                  >
                    {(typeOptions.length > 0 ? typeOptions : CAMPAIGN_DELIVERABLE_TYPES.map((o) => o.value)).map(
                      (type) => {
                        const label =
                          CAMPAIGN_DELIVERABLE_TYPES.find((option) => option.value === type)?.label ?? type;
                        return (
                          <option key={type} value={type}>
                            {label}
                          </option>
                        );
                      },
                    )}
                  </select>
                  <FieldError
                    id={`${formId}-deliverable-type-${index}-error`}
                    message={firstFieldError(fieldErrors, `deliverables.${index}.type`)}
                  />
                </div>
                <div className="sm:col-span-2">
                  <TextField
                    id={`${formId}-deliverable-qty-${index}`}
                    label={qtyField.label}
                    required={qtyField.required}
                    type="number"
                    min={1}
                    max={100}
                    value={item.quantity}
                    disabled={disabled}
                    error={firstFieldError(fieldErrors, `deliverables.${index}.quantity`)}
                    onChange={(value) => updateDeliverable(index, { quantity: value })}
                  />
                </div>
                <div className="sm:col-span-5">
                  <TextField
                    id={`${formId}-deliverable-desc-${index}`}
                    label={descField.label}
                    required={descField.required}
                    value={item.description}
                    disabled={disabled}
                    error={firstFieldError(fieldErrors, `deliverables.${index}.description`)}
                    onChange={(value) => updateDeliverable(index, { description: value })}
                  />
                </div>
                <div className="flex items-end sm:col-span-1">
                  <Button
                    type="button"
                    variant="secondary"
                    size="sm"
                    className="w-full"
                    disabled={disabled || values.deliverables.length <= 1}
                    onClick={() => {
                      setValues((current) => ({
                        ...current,
                        deliverables: current.deliverables.filter((_, itemIndex) => itemIndex !== index),
                      }));
                      setInstructionsOpenIndexes((current) => {
                        const next = new Set<number>();
                        for (const openIndex of current) {
                          if (openIndex < index) next.add(openIndex);
                          else if (openIndex > index) next.add(openIndex - 1);
                        }
                        return next;
                      });
                    }}
                  >
                    Remove
                  </Button>
                </div>

                <div className="sm:col-span-12">
                  {!instructionsOpen ? (
                    <button
                      type="button"
                      disabled={disabled}
                      className="text-[0.8125rem] font-medium text-primary underline-offset-2 hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
                      onClick={() => toggleInstructions(index)}
                    >
                      {hasInstructions ? "Edit instructions" : "+ Add instructions"}
                    </button>
                  ) : (
                    <div className="space-y-3 border-t border-line pt-3">
                      <TextAreaField
                        id={`${formId}-deliverable-instructions-${index}`}
                        label={instructionsField.label}
                        required={instructionsField.required}
                        value={item.creator_instructions}
                        disabled={disabled}
                        rows={2}
                        error={firstFieldError(fieldErrors, `deliverables.${index}.creator_instructions`)}
                        onChange={(value) => updateDeliverable(index, { creator_instructions: value })}
                      />
                      <TextField
                        id={`${formId}-deliverable-ref-${index}`}
                        label={referenceField.label}
                        required={referenceField.required}
                        value={item.reference_url}
                        disabled={disabled}
                        error={firstFieldError(fieldErrors, `deliverables.${index}.reference_url`)}
                        onChange={(value) => updateDeliverable(index, { reference_url: value })}
                      />
                      <button
                        type="button"
                        disabled={disabled}
                        className="text-[0.8125rem] font-medium text-ink-60 hover:text-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent"
                        onClick={() => toggleInstructions(index)}
                      >
                        Hide instructions
                      </button>
                    </div>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      </section>

      <FormSection title="Budget">
        <TextField
          id={`${formId}-budget`}
          label={CAMPAIGN_FIELD_REQUIREMENTS.budgetAmount.label}
          required={CAMPAIGN_FIELD_REQUIREMENTS.budgetAmount.required}
          value={values.budgetMajor}
          disabled={disabled}
          inputMode="decimal"
          error={firstFieldError(fieldErrors, "budget_amount")}
          onChange={(value) => update("budgetMajor", value)}
          hint="USD. Enter dollars. Stored as cents (e.g. 5000 = $5,000.00)."
          span
        />
      </FormSection>

      <FormSection title="Timeline">
        <TextField
          id={`${formId}-start`}
          label={CAMPAIGN_FIELD_REQUIREMENTS.startDate.label}
          required={CAMPAIGN_FIELD_REQUIREMENTS.startDate.required}
          type="date"
          value={values.startDate}
          disabled={disabled}
          error={firstFieldError(fieldErrors, "start_date")}
          onChange={(value) => update("startDate", value)}
        />
        <TextField
          id={`${formId}-end`}
          label={CAMPAIGN_FIELD_REQUIREMENTS.endDate.label}
          required={CAMPAIGN_FIELD_REQUIREMENTS.endDate.required}
          type="date"
          value={values.endDate}
          disabled={disabled}
          error={firstFieldError(fieldErrors, "end_date")}
          onChange={(value) => update("endDate", value)}
        />
      </FormSection>

      {mode === "edit" ? (
        <FormSection title="Status">
          <div className="sm:col-span-2">
            <p className="text-[0.6875rem] font-medium uppercase tracking-[0.06em] text-ink-40">
              {CAMPAIGN_FIELD_REQUIREMENTS.status.label}
            </p>
            <p className="mt-1 text-[0.875rem] font-medium text-primary">
              {values.status.charAt(0).toUpperCase() + values.status.slice(1)}
            </p>
            <p className="mt-1 text-[0.75rem] text-ink-40">
              Use Activate, Pause, Resume, Complete, or Cancel on the campaign page to change
              status.
            </p>
          </div>
        </FormSection>
      ) : null}

      <div className="flex flex-wrap gap-2 border-t border-line pt-4">
        {mode === "create" ? (
          <>
            <Button
              type="button"
              variant="secondary"
              size="sm"
              disabled={disabled}
              onClick={() => onSubmit(values, "draft")}
            >
              {busyAction === "draft" ? "Saving…" : "Save draft"}
            </Button>
            <Button
              type="button"
              size="sm"
              disabled={disabled}
              onClick={() => onSubmit(values, "active")}
            >
              {busyAction === "active" ? "Creating…" : "Create campaign"}
            </Button>
          </>
        ) : (
          <Button
            type="button"
            size="sm"
            disabled={disabled}
            onClick={() => onSubmit(values, values.status)}
          >
            {busyAction === "save" ? "Saving…" : "Save changes"}
          </Button>
        )}
        {onCancel ? (
          <Button type="button" variant="secondary" size="sm" disabled={disabled} onClick={onCancel}>
            Cancel
          </Button>
        ) : null}
      </div>
    </form>
  );
}
