"use client";

import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { Tag, X } from "lucide-react";
import { fileToDataUrl } from "@/lib/image";
import { useCurrency } from "@/lib/currency";
import { DISCOUNT_TYPES } from "@/lib/jobs";
import type { DiscountType } from "@/lib/types";

type Category = { id: string; name: string; enabled: boolean };

/**
 * Posting an offer.
 *
 * The kind of deal is chosen first and everything below changes to match, so
 * a percent deal never shows a "buy how many" box. Sngine keeps all four
 * sets of fields on the page and hides them with JavaScript, which is how
 * people fill in the wrong pair and wonder why nothing saves.
 */
export function CreateOfferModal({
  onClose,
  onCreated,
}: {
  onClose: () => void;
  onCreated?: () => void;
}) {
  const { symbol } = useCurrency();
  const [categories, setCategories] = useState<Category[]>([]);
  const [kind, setKind] = useState<DiscountType>("percent");
  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [category, setCategory] = useState("");
  const [location, setLocation] = useState("");
  const [price, setPrice] = useState("");
  const [endsAt, setEndsAt] = useState("");
  const [thumbnail, setThumbnail] = useState<string | undefined>();
  const [nums, setNums] = useState<Record<string, string>>({});
  const [error, setError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    fetch("/api/admin/categories?module=offers")
      .then((r) => r.json())
      .then((rows) => Array.isArray(rows) && setCategories(rows.filter((c) => c.enabled)))
      .catch(() => {});
  }, []);

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);

  const num = (k: string) => nums[k] ?? "";
  const setNum = (k: string, v: string) =>
    setNums((n) => ({ ...n, [k]: v.replace(/[^\d.]/g, "") }));

  /** The one or two numbers this kind of deal actually needs, and their unit. */
  const fields: { key: string; label: string; unit?: string; hint?: string }[] =
    kind === "percent"
      ? [{ key: "discountPercent", label: "Percent off", unit: "%", hint: "1 to 100" }]
      : kind === "amount"
      ? [{ key: "discountAmount", label: "Amount off", unit: symbol }]
      : kind === "buy_x_get_y"
      ? [
          { key: "buyX", label: "Buy this many" },
          { key: "getY", label: "Get this many free" },
        ]
      : [
          { key: "spendX", label: "Spend at least", unit: symbol },
          { key: "amountY", label: "And take off", unit: symbol },
        ];

  async function submit() {
    setError(null);
    if (!title.trim()) return setError("Give the offer a title");
    if (!description.trim()) return setError("Describe the offer");
    for (const f of fields) {
      if (!num(f.key)) return setError("Fill in " + f.label.toLowerCase());
    }

    setSaving(true);
    const res = await fetch("/api/offers", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        title,
        description,
        category: category || undefined,
        location: location || undefined,
        discountType: kind,
        ...Object.fromEntries(fields.map((f) => [f.key, Number(num(f.key))])),
        price: price ? Number(price) : undefined,
        endsAt: endsAt ? new Date(endsAt).toISOString() : undefined,
        thumbnail,
      }),
    });
    setSaving(false);

    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      return setError(body.error || "That didn't save");
    }
    onCreated?.();
    onClose();
  }

  return createPortal(
    <div className="nm-back" onClick={onClose}>
      <div className="jb-modal" onClick={(e) => e.stopPropagation()}>
        <header className="jb-mhead">
          <h2 className="jb-mtitle">
            <Tag size={18} /> Post an offer
          </h2>
          <button className="jb-mx" onClick={onClose} aria-label="Close">
            <X size={18} />
          </button>
        </header>

        <div className="jb-mbody">
          <section className="jb-sec">
            <label className="jb-label">What kind of deal?</label>
            <div className="jb-chips" style={{ marginBottom: 16 }}>
              {DISCOUNT_TYPES.map((d) => (
                <button
                  key={d.value}
                  type="button"
                  className={"jb-chip offers" + (kind === d.value ? " on" : "")}
                  onClick={() => setKind(d.value)}
                >
                  {d.label}
                </button>
              ))}
            </div>

            <div className={fields.length > 1 ? "jb-row" : ""}>
              {fields.map((f) => (
                <div key={f.key}>
                  <label className="jb-label">
                    {f.label} <span className="jb-req">*</span>
                  </label>
                  <div className="jb-money">
                    {f.unit && <span className="jb-cur">{f.unit}</span>}
                    <input
                      className="jb-field"
                      style={f.unit ? undefined : { paddingLeft: 13 }}
                      inputMode="decimal"
                      value={num(f.key)}
                      placeholder={f.hint}
                      onChange={(e) => setNum(f.key, e.target.value)}
                    />
                  </div>
                </div>
              ))}
            </div>
          </section>

          <section className="jb-sec">
            <label className="jb-label">
              Title <span className="jb-req">*</span>
            </label>
            <input
              className="jb-field"
              value={title}
              maxLength={100}
              placeholder="20% off everything this weekend"
              onChange={(e) => setTitle(e.target.value)}
            />

            <label className="jb-label" style={{ marginTop: 14 }}>
              Details <span className="jb-req">*</span>
            </label>
            <textarea
              className="jb-field"
              rows={4}
              value={description}
              maxLength={5000}
              placeholder="What it covers, anything it doesn't, how to claim it."
              onChange={(e) => setDescription(e.target.value)}
            />

            <div className="jb-row" style={{ marginTop: 14 }}>
              <div>
                <label className="jb-label">Category</label>
                <select
                  className="jb-field"
                  value={category}
                  onChange={(e) => setCategory(e.target.value)}
                >
                  <option value="">Choose one</option>
                  {categories.map((c) => (
                    <option key={c.id} value={c.name}>
                      {c.name}
                    </option>
                  ))}
                </select>
              </div>
              <div>
                <label className="jb-label">Location</label>
                <input
                  className="jb-field"
                  value={location}
                  maxLength={100}
                  placeholder="Where it applies"
                  onChange={(e) => setLocation(e.target.value)}
                />
              </div>
            </div>

            <div className="jb-row" style={{ marginTop: 14 }}>
              <div>
                <label className="jb-label">
                  Normal price <span className="jb-opt">optional</span>
                </label>
                <div className="jb-money">
                  <span className="jb-cur">{symbol}</span>
                  <input
                    className="jb-field"
                    inputMode="decimal"
                    value={price}
                    onChange={(e) => setPrice(e.target.value.replace(/[^\d.]/g, ""))}
                  />
                </div>
              </div>
              <div>
                <label className="jb-label">
                  Ends <span className="jb-opt">optional</span>
                </label>
                <input
                  type="date"
                  className="jb-field"
                  value={endsAt}
                  onChange={(e) => setEndsAt(e.target.value)}
                />
              </div>
            </div>
          </section>

          <section className="jb-sec">
            <label className="jb-label">
              Picture <span className="jb-opt">optional</span>
            </label>
            <input
              type="file"
              accept="image/*"
              className="jb-field"
              onChange={async (e) => {
                const file = e.target.files?.[0];
                if (file) setThumbnail(await fileToDataUrl(file, 1200));
              }}
            />
            {thumbnail && (
              // eslint-disable-next-line @next/next/no-img-element
              <img className="jb-cover" src={thumbnail} alt="" />
            )}
          </section>

          {error && <p className="jb-error">{error}</p>}
        </div>

        <footer className="jb-mfoot">
          <button className="jb-btn offers wide big" onClick={submit} disabled={saving}>
            {saving ? "Posting…" : "Post the offer"}
          </button>
        </footer>
      </div>
    </div>,
    document.body
  );
}
