"use client";

import { useCallback, useEffect, useMemo, useState, type FormEvent } from "react";
import { toast } from "sonner";
import { Button } from "@/components/Button";
import { DashboardPageContainer } from "@/components/dashboard/DashboardPageContainer";
import { DashboardShell } from "@/components/dashboard/DashboardShell";
import { EmptyState } from "@/components/ui/EmptyState";
import { ErrorState } from "@/components/ui/ErrorState";
import { PageHeader, SectionHeader } from "@/components/ui/PageHeader";
import { StatusBadge } from "@/components/ui/StatusBadge";
import { fieldClassName, fieldInvalidClassName, textareaClassName } from "@/components/ui/field-styles";
import { ApiError } from "@/lib/api";
import { rateCardApi } from "@/lib/api/rates";
import { cn } from "@/lib/cn";
import { minorToMajorInput } from "@/lib/campaigns";
import { formatMoneyMinor } from "@/lib/format";
import {
  RATE_CARD_EMPTY_MESSAGE,
  RATE_CARD_EXPLANATION,
  RATE_SERVICE_OPTIONS,
  rateCardViewState,
  rateServiceLabel,
  rateStatusBadgeVariant,
  rateStatusLabel,
  validateRateItemForm,
  type RateItemFormErrors,
} from "@/lib/rates";
import type { RateCard, RateCardItem, RateCardServiceType } from "@/types/rates";

const CREATOR_ONLY = ["creator"] as const;

type EditorMode = { kind: "closed" } | { kind: "create" } | { kind: "edit"; item: RateCardItem };

export function DashboardRatesSettingsPage() {
  return (
    <DashboardShell title="Creator Rates" allowedAccountTypes={CREATOR_ONLY}>
      {() => <RatesSettingsContent />}
    </DashboardShell>
  );
}

function RatesSettingsContent() {
  const [card, setCard] = useState<RateCard | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [editor, setEditor] = useState<EditorMode>({ kind: "closed" });
  const [busyItemId, setBusyItemId] = useState<number | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const next = await rateCardApi.get();
      setCard(next);
    } catch (caught) {
      setCard(null);
      setError(caught instanceof ApiError ? caught.message : "Unable to load rate card.");
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    void load();
  }, [load]);

  const view = rateCardViewState({
    loading,
    error,
    itemCount: card ? card.items.length : null,
  });

  const usedServiceTypes = useMemo(() => {
    return new Set((card?.items ?? []).map((item) => item.service_type));
  }, [card]);

  const upsertItem = useCallback((item: RateCardItem) => {
    setCard((current) => {
      if (!current) {
        return current;
      }
      const index = current.items.findIndex((entry) => entry.id === item.id);
      if (index === -1) {
        return { ...current, items: [...current.items, item] };
      }
      const items = [...current.items];
      items[index] = item;
      return { ...current, items };
    });
  }, []);

  const onToggleActive = useCallback(
    async (item: RateCardItem) => {
      setBusyItemId(item.id);
      try {
        const next = item.is_active
          ? await rateCardApi.deactivateItem(item.id)
          : await rateCardApi.activateItem(item.id);
        upsertItem(next);
        toast.success(next.is_active ? "Rate reactivated." : "Rate deactivated.");
      } catch (caught) {
        toast.error(caught instanceof ApiError ? caught.message : "Unable to update rate status.");
      } finally {
        setBusyItemId(null);
      }
    },
    [upsertItem],
  );

  return (
    <DashboardPageContainer className="max-w-2xl px-4 py-8 sm:px-6">
      <PageHeader description="Manage the prices brands see when planning creator work." />

      <section aria-labelledby="creator-rates-heading" className="space-y-4">
        <SectionHeader
          id="creator-rates-heading"
          title="Creator Rates"
          description={RATE_CARD_EXPLANATION}
          action={
            <Button
              type="button"
              size="sm"
              disabled={loading || editor.kind !== "closed"}
              onClick={() => setEditor({ kind: "create" })}
            >
              Add rate
            </Button>
          }
        />

        {view.kind === "loading" ? (
          <div className="h-28 animate-pulse rounded-pv border border-line bg-line/40" aria-hidden="true" />
        ) : null}

        {view.kind === "error" ? (
          <ErrorState
            title="Unable to load rate card"
            message={view.message}
            onRetry={() => {
              void load();
            }}
          />
        ) : null}

        {editor.kind !== "closed" ? (
          <RateItemEditor
            mode={editor}
            currency={card?.currency ?? "USD"}
            usedServiceTypes={usedServiceTypes}
            onCancel={() => setEditor({ kind: "closed" })}
            onSaved={(item) => {
              upsertItem(item);
              setEditor({ kind: "closed" });
              toast.success(editor.kind === "create" ? "Rate added." : "Rate updated.");
            }}
          />
        ) : null}

        {view.kind === "empty" && editor.kind === "closed" ? (
          <EmptyState title="No rates yet" description={RATE_CARD_EMPTY_MESSAGE} />
        ) : null}

        {card && card.items.length > 0 ? (
          <ul className="space-y-3">
            {card.items.map((item) => (
              <li key={item.id} className="rounded-pv border border-line bg-surface p-4">
                <div className="flex flex-wrap items-start justify-between gap-3">
                  <div className="min-w-0 space-y-1">
                    <div className="flex flex-wrap items-center gap-2">
                      <h3 className="text-[0.9375rem] font-semibold text-primary">{item.title}</h3>
                      <StatusBadge variant={rateStatusBadgeVariant(item.is_active)}>
                        {rateStatusLabel(item.is_active)}
                      </StatusBadge>
                    </div>
                    <p className="text-[0.8125rem] text-ink-60">{rateServiceLabel(item.service_type)}</p>
                    {item.description ? (
                      <p className="text-[0.8125rem] text-ink-60">{item.description}</p>
                    ) : null}
                    <p className="text-[0.9375rem] font-medium text-primary">
                      {formatMoneyMinor(item.price_amount, item.currency)}
                      <span className="ml-1 text-[0.75rem] font-normal text-ink-60">{item.currency}</span>
                    </p>
                  </div>
                  <div className="flex shrink-0 flex-wrap gap-2">
                    <Button
                      type="button"
                      size="sm"
                      variant="secondary"
                      disabled={busyItemId === item.id || editor.kind !== "closed"}
                      onClick={() => setEditor({ kind: "edit", item })}
                    >
                      Edit
                    </Button>
                    <Button
                      type="button"
                      size="sm"
                      variant="secondary"
                      disabled={busyItemId === item.id || editor.kind !== "closed"}
                      aria-busy={busyItemId === item.id}
                      onClick={() => {
                        void onToggleActive(item);
                      }}
                    >
                      {item.is_active ? "Deactivate" : "Reactivate"}
                    </Button>
                  </div>
                </div>
              </li>
            ))}
          </ul>
        ) : null}
      </section>
    </DashboardPageContainer>
  );
}

function RateItemEditor({
  mode,
  currency,
  usedServiceTypes,
  onCancel,
  onSaved,
}: {
  mode: Exclude<EditorMode, { kind: "closed" }>;
  currency: string;
  usedServiceTypes: Set<RateCardServiceType>;
  onCancel: () => void;
  onSaved: (item: RateCardItem) => void;
}) {
  const editing = mode.kind === "edit" ? mode.item : null;
  const [serviceType, setServiceType] = useState<string>(editing?.service_type ?? "");
  const [title, setTitle] = useState(editing?.title ?? "");
  const [description, setDescription] = useState(editing?.description ?? "");
  const [priceMajor, setPriceMajor] = useState(
    editing ? minorToMajorInput(editing.price_amount) : "",
  );
  const [errors, setErrors] = useState<RateItemFormErrors>({});
  const [submitting, setSubmitting] = useState(false);

  const availableServices = RATE_SERVICE_OPTIONS.filter(
    (option) =>
      !usedServiceTypes.has(option.value) || option.value === editing?.service_type,
  );

  const onSubmit = async (event: FormEvent) => {
    event.preventDefault();
    const validated = validateRateItemForm({
      service_type: serviceType,
      title,
      description,
      priceMajor,
      requireServiceType: mode.kind === "create",
    });

    if (Object.keys(validated.errors).length > 0 || validated.price_amount === null) {
      setErrors(validated.errors);
      return;
    }

    setSubmitting(true);
    setErrors({});

    try {
      if (mode.kind === "create") {
        const item = await rateCardApi.createItem({
          service_type: serviceType as RateCardServiceType,
          title: title.trim(),
          description: description.trim() || null,
          price_amount: validated.price_amount,
          currency,
        });
        onSaved(item);
      } else {
        const item = await rateCardApi.updateItem(mode.item.id, {
          title: title.trim(),
          description: description.trim() || null,
          price_amount: validated.price_amount,
          currency,
        });
        onSaved(item);
      }
    } catch (caught) {
      if (caught instanceof ApiError && caught.kind === "validation") {
        const next: RateItemFormErrors = {};
        for (const [key, messages] of Object.entries(caught.errors)) {
          if (messages[0]) {
            next[key as keyof RateItemFormErrors] = messages[0];
          }
        }
        next.form = caught.message;
        setErrors(next);
      } else {
        setErrors({
          form: caught instanceof ApiError ? caught.message : "Unable to save rate.",
        });
      }
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <form
      noValidate
      onSubmit={(event) => {
        void onSubmit(event);
      }}
      className="space-y-3 rounded-pv border border-line bg-surface p-4"
    >
      <h3 className="text-[0.875rem] font-semibold text-primary">
        {mode.kind === "create" ? "Add rate" : "Edit rate"}
      </h3>

      {mode.kind === "create" ? (
        <label className="block space-y-1">
          <span className="text-[0.8125rem] font-medium text-primary">Service</span>
          <select
            className={cn(fieldClassName, errors.service_type && fieldInvalidClassName)}
            value={serviceType}
            onChange={(event) => setServiceType(event.target.value)}
            disabled={submitting || availableServices.length === 0}
          >
            <option value="">Select a service</option>
            {availableServices.map((option) => (
              <option key={option.value} value={option.value}>
                {option.label}
              </option>
            ))}
          </select>
          {errors.service_type ? (
            <span className="block text-[0.75rem] text-red-700">{errors.service_type}</span>
          ) : null}
        </label>
      ) : (
        <p className="text-[0.8125rem] text-ink-60">
          Service: {rateServiceLabel(mode.item.service_type)}
        </p>
      )}

      <label className="block space-y-1">
        <span className="text-[0.8125rem] font-medium text-primary">Title</span>
        <input
          className={cn(fieldClassName, errors.title && fieldInvalidClassName)}
          value={title}
          onChange={(event) => setTitle(event.target.value)}
          disabled={submitting}
          maxLength={120}
        />
        {errors.title ? <span className="block text-[0.75rem] text-red-700">{errors.title}</span> : null}
      </label>

      <label className="block space-y-1">
        <span className="text-[0.8125rem] font-medium text-primary">Description</span>
        <textarea
          className={cn(textareaClassName, errors.description && fieldInvalidClassName)}
          value={description}
          onChange={(event) => setDescription(event.target.value)}
          disabled={submitting}
          maxLength={500}
          rows={3}
        />
        {errors.description ? (
          <span className="block text-[0.75rem] text-red-700">{errors.description}</span>
        ) : null}
      </label>

      <label className="block space-y-1">
        <span className="text-[0.8125rem] font-medium text-primary">Price ({currency})</span>
        <input
          className={cn(fieldClassName, errors.price_amount && fieldInvalidClassName)}
          value={priceMajor}
          onChange={(event) => setPriceMajor(event.target.value)}
          disabled={submitting}
          inputMode="decimal"
          placeholder="250.00"
        />
        {errors.price_amount ? (
          <span className="block text-[0.75rem] text-red-700">{errors.price_amount}</span>
        ) : null}
      </label>

      {errors.form ? (
        <p className="text-[0.8125rem] text-red-700" role="alert">
          {errors.form}
        </p>
      ) : null}

      <div className="flex flex-wrap gap-2">
        <Button type="submit" size="sm" disabled={submitting} aria-busy={submitting}>
          {submitting ? "Saving…" : "Save rate"}
        </Button>
        <Button type="button" size="sm" variant="secondary" disabled={submitting} onClick={onCancel}>
          Cancel
        </Button>
      </div>
    </form>
  );
}
