"use client";

import { useActionState, useEffect, useMemo, useRef, useState } from "react";
import { useFormStatus } from "react-dom";
import { Trash2 } from "lucide-react";
import { toast } from "sonner";
import ConfirmDialog from "@/components/ui/ConfirmDialog";
import { addressLookupApi } from "@/lib/api/addressLookup";
import type { ApiSellerForPrice } from "@/lib/api/types";
import { removeProductForPrice, saveProductForPrice } from "./actions";
import {
  FieldError,
  FormErrorSummary,
  INITIAL_UPDATE_STATE,
  Label,
  SubmitButton,
  inputClass,
} from "./updates/shared";

const OWN_FIELDS = ["state", "city", "price"];

/**
 * Removing a quote is not a small change — that city's buyers go back to the
 * calculated F.O.R price, which can be a very different number — so the click is
 * intercepted and re-submitted only once confirmed.
 *
 * Lives in its own component so `useFormStatus` reports on this row's form
 * rather than the whole table's.
 */
function RemoveButton({ city }: { city: string }) {
  const { pending } = useFormStatus();
  const btnRef = useRef<HTMLButtonElement>(null);
  const [open, setOpen] = useState(false);

  return (
    <>
      <button
        ref={btnRef}
        type="submit"
        onClick={(e) => {
          e.preventDefault();
          setOpen(true);
        }}
        disabled={pending}
        className="rounded-md p-2 text-[#CC1414] hover:bg-rose-50 disabled:opacity-50"
        aria-label={`Remove F.O.R price for ${city}`}
      >
        <Trash2 className="h-4 w-4" />
      </button>

      <ConfirmDialog
        open={open}
        title={`Remove the F.O.R price for ${city}?`}
        description="Buyers there will go back to the calculated F.O.R price (Ex Price + freight)."
        confirmLabel="Remove"
        loading={pending}
        onCancel={() => setOpen(false)}
        onConfirm={() => {
          setOpen(false);
          const btn = btnRef.current;
          btn?.form?.requestSubmit(btn);
        }}
      />
    </>
  );
}

const inr = new Intl.NumberFormat("en-IN", {
  style: "currency",
  currency: "INR",
  maximumFractionDigits: 0,
});

/**
 * City-wise freight for one listing, and the F.O.R price it produces.
 *
 * The seller quotes what it costs to move a tonne to a city; the buyer's F.O.R
 * (doorstep) price is this listing's ex-works price plus that. Cities left
 * unquoted fall back to the cheapest transporter rate.
 *
 * Create and update are the same submit: picking a city that is already quoted
 * fills the input with its rate, and saving overwrites it.
 */
export default function ForPriceForm({
  productId,
  slug,
  exPrice,
  states,
  prices,
}: {
  productId: number;
  /** Freight changes the public F.O.R price, so that page is invalidated too. */
  slug: string | null;
  /** The listing's ex-works price — the other half of every F.O.R below. */
  exPrice: number;
  states: string[];
  prices: ApiSellerForPrice[];
}) {
  const [state, formAction] = useActionState(saveProductForPrice, INITIAL_UPDATE_STATE);
  const [removeState, removeAction] = useActionState(removeProductForPrice, INITIAL_UPDATE_STATE);

  const [selectedState, setSelectedState] = useState("");
  const [selectedCity, setSelectedCity] = useState("");
  const [cities, setCities] = useState<string[]>([]);
  const [loadingCities, setLoadingCities] = useState(false);
  const [price, setPrice] = useState("");

  /** What this city is already priced at, if anything. */
  const existing = useMemo(
    () =>
      prices.find(
        (row) => row.state === selectedState && row.city === selectedCity
      ) ?? null,
    [prices, selectedState, selectedCity]
  );

  useEffect(() => {
    if (!selectedState) {
      setCities([]);
      setSelectedCity("");
      return;
    }

    let active = true;
    setLoadingCities(true);
    setSelectedCity("");
    addressLookupApi
      .cities(selectedState)
      .then((list) => {
        if (active) setCities(list);
      })
      .catch(() => {
        if (active) setCities([]);
      })
      .finally(() => {
        if (active) setLoadingCities(false);
      });

    return () => {
      active = false;
    };
  }, [selectedState]);

  /* Seed the input from the saved price so the seller sees what they are
     changing, rather than typing into a blank box beside a city that already
     has a number. */
  useEffect(() => {
    setPrice(existing?.price ?? "");
  }, [existing]);

  useEffect(() => {
    const result = state.ok ? state : removeState;
    if (result.message) {
      if (result.ok) toast.success(result.message);
      else toast.error(result.message);
    }
  }, [state, removeState]);

  /*
    React resets the <form> once a server action settles, which blanks the two
    selects in the DOM even though this component still holds the selection —
    the price box kept its value only because an effect re-applied it. Remounting
    the fields re-applies all three, so the seller stays on the city they just
    quoted instead of losing their place after every save.
  */
  const [fieldsKey, setFieldsKey] = useState(0);
  useEffect(() => {
    if (state.ok) setFieldsKey((n) => n + 1);
  }, [state]);

  return (
    <div className="space-y-4">
      <form action={formAction} className="space-y-3">
        <input type="hidden" name="id" value={productId} />
        {slug ? <input type="hidden" name="slug" value={slug} /> : null}

        <div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-4">
          <div>
            <Label required>State</Label>
            <select
              key={`state-${fieldsKey}`}
              name="state"
              value={selectedState}
              onChange={(e) => setSelectedState(e.target.value)}
              className={inputClass}
            >
              <option value="">Select state</option>
              {states.map((name) => (
                <option key={name} value={name}>
                  {name}
                </option>
              ))}
            </select>
            <FieldError messages={state.errors.state} />
          </div>

          <div>
            <Label required>City</Label>
            <select
              key={`city-${fieldsKey}`}
              name="city"
              value={selectedCity}
              onChange={(e) => setSelectedCity(e.target.value)}
              className={inputClass}
              disabled={!selectedState || loadingCities}
            >
              <option value="">
                {!selectedState
                  ? "Select state first"
                  : loadingCities
                    ? "Loading…"
                    : cities.length
                      ? "Select city"
                      : "No cities found"}
              </option>
              {cities.map((name) => (
                <option key={name} value={name}>
                  {name}
                </option>
              ))}
            </select>
            <FieldError messages={state.errors.city} />
          </div>

          <div>
            <Label required>Freight per MT (₹)</Label>
            <input
              key={`price-${fieldsKey}`}
              name="price"
              value={price}
              onChange={(e) => setPrice(e.target.value)}
              className={inputClass}
              placeholder="Enter freight"
              inputMode="decimal"
              disabled={!selectedCity}
            />
            <FieldError messages={state.errors.price} />
          </div>

          <div className="flex items-end">
            <SubmitButton label={existing ? "Update freight" : "Add freight"} />
          </div>
        </div>

        <FormErrorSummary state={state} own={OWN_FIELDS} />

        {existing ? (
          <p className="text-xs text-emerald-700">
            {selectedCity} is already quoted at {inr.format(Number(existing.price) || 0)} per MT —
            an F.O.R price of {inr.format(exPrice + (Number(existing.price) || 0))}. Saving replaces
            it.
          </p>
        ) : (
          <p className="text-xs text-gray-500">
            F.O.R Price = Ex Price ({inr.format(exPrice)}) + freight. Cities you don’t quote fall
            back to the cheapest transporter rate.
          </p>
        )}
      </form>

      {prices.length === 0 ? (
        <p className="rounded-lg bg-gray-50 p-3 text-sm text-gray-500">
          No city freight yet. Buyers everywhere see the calculated F.O.R price.
        </p>
      ) : (
        <div className="overflow-x-auto">
          {/* Wider than before: the two timestamp columns do not compress, so
              the wrapper scrolls rather than letting the prices wrap. */}
          <table className="w-full min-w-[820px] text-sm">
            <thead>
              <tr className="border-b border-gray-200 text-left text-xs font-medium text-gray-500">
                <th className="pb-2 pr-3">State</th>
                <th className="pb-2 pr-3">City</th>
                <th className="pb-2 pr-3 text-right">Ex Price</th>
                <th className="pb-2 pr-3 text-right">Freight / MT</th>
                <th className="pb-2 pr-3 text-right">F.O.R Price</th>
                <th className="pb-2 pr-3 whitespace-nowrap">Created</th>
                <th className="pb-2 pr-3 whitespace-nowrap">Updated</th>
                <th className="pb-2 text-right">Action</th>
              </tr>
            </thead>
            <tbody>
              {prices.map((row) => {
                const freight = Number(row.price) || 0;
                return (
                  <tr key={row.id} className="border-b border-gray-50 last:border-0">
                    <td className="py-2 pr-3 text-gray-700">{row.state}</td>
                    <td className="py-2 pr-3 font-medium text-gray-900">{row.city}</td>
                    <td className="py-2 pr-3 text-right tabular-nums text-gray-500">
                      {inr.format(exPrice)}
                    </td>
                    <td className="py-2 pr-3 text-right tabular-nums text-gray-500">
                      + {inr.format(freight)}
                    </td>
                    <td className="py-2 pr-3 text-right font-semibold tabular-nums text-gray-900">
                      {inr.format(exPrice + freight)}
                    </td>
                    <td className="py-2 pr-3 whitespace-nowrap text-xs text-gray-500">
                      {row.created_at ?? "—"}
                    </td>
                    <td className="py-2 pr-3 whitespace-nowrap text-xs text-gray-500">
                      {row.updated_at ?? "—"}
                    </td>
                    <td className="py-2 text-right">
                      <form action={removeAction} className="inline">
                        <input type="hidden" name="id" value={productId} />
                        {slug ? <input type="hidden" name="slug" value={slug} /> : null}
                        <input type="hidden" name="price_id" value={row.id} />
                        <RemoveButton city={row.city} />
                      </form>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}
