"use client";

import { useEffect, useState } from "react";
import { createPortal } from "react-dom";
import { Briefcase, Plus, Trash2, X } from "lucide-react";
import { fileToDataUrl } from "@/lib/image";
import { useCurrency } from "@/lib/currency";
import { JOB_TYPES, PAY_PER } from "@/lib/jobs";
import type { JobQuestion, JobType, PayPer } from "@/lib/types";

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

/**
 * Posting a job.
 *
 * Three sections — the role, the pay, the questions — because the pay is
 * where people stall, and burying it halfway down one long column is how a
 * form gets abandoned.
 */
export function CreateJobModal({
  onClose,
  onCreated,
}: {
  onClose: () => void;
  onCreated?: () => void;
}) {
  const { symbol } = useCurrency();
  const [categories, setCategories] = useState<Category[]>([]);
  const [title, setTitle] = useState("");
  const [description, setDescription] = useState("");
  const [category, setCategory] = useState("");
  const [location, setLocation] = useState("");
  const [type, setType] = useState<JobType>("full_time");
  // Hourly first: it is what most adverts on a site like this are, and it
  // is the figure people can check against their own without arithmetic.
  const [payPer, setPayPer] = useState<PayPer>("per_hour");
  const [salaryMin, setSalaryMin] = useState("");
  const [salaryMax, setSalaryMax] = useState("");
  const [coverImage, setCoverImage] = useState<string | undefined>();
  const [questions, setQuestions] = useState<JobQuestion[]>([]);
  const [error, setError] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    fetch("/api/admin/categories?module=jobs")
      .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 setQuestion = (i: number, patch: Partial<JobQuestion>) =>
    setQuestions((qs) => qs.map((q, n) => (n === i ? { ...q, ...patch } : q)));

  async function submit() {
    setError(null);
    if (!title.trim()) return setError("Give the job a title");
    if (!description.trim()) return setError("Describe the role");
    if (salaryMin && salaryMax && Number(salaryMax) < Number(salaryMin)) {
      return setError("The top of the range is below the bottom");
    }

    setSaving(true);
    const res = await fetch("/api/jobs", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        title,
        description,
        category: category || undefined,
        location: location || undefined,
        type,
        payPer,
        salaryMin: salaryMin ? Number(salaryMin) : undefined,
        salaryMax: salaryMax ? Number(salaryMax) : undefined,
        coverImage,
        questions,
      }),
    });
    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">
            <Briefcase size={18} /> Post a job
          </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">
              Job title <span className="jb-req">*</span>
            </label>
            <input
              className="jb-field"
              value={title}
              maxLength={100}
              placeholder="Senior barista"
              onChange={(e) => setTitle(e.target.value)}
            />

            <label className="jb-label" style={{ marginTop: 14 }}>
              Description <span className="jb-req">*</span>
            </label>
            <textarea
              className="jb-field"
              rows={5}
              value={description}
              maxLength={5000}
              placeholder="What the job involves, who you're looking for, how to stand out."
              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="Manchester, or Remote"
                  onChange={(e) => setLocation(e.target.value)}
                />
              </div>
            </div>
          </section>

          <section className="jb-sec">
            <label className="jb-label">Pay</label>
            <div className="jb-range">
              <div className="jb-money">
                <span className="jb-cur">{symbol}</span>
                <input
                  className="jb-field"
                  inputMode="decimal"
                  value={salaryMin}
                  placeholder="From"
                  onChange={(e) => setSalaryMin(e.target.value.replace(/[^\d.]/g, ""))}
                />
              </div>
              <span className="jb-rangebar" aria-hidden />
              <div className="jb-money">
                <span className="jb-cur">{symbol}</span>
                <input
                  className="jb-field"
                  inputMode="decimal"
                  value={salaryMax}
                  placeholder="To"
                  onChange={(e) => setSalaryMax(e.target.value.replace(/[^\d.]/g, ""))}
                />
              </div>
              <select
                className="jb-field"
                style={{ width: "auto" }}
                value={payPer}
                onChange={(e) => setPayPer(e.target.value as PayPer)}
              >
                {PAY_PER.map((p) => (
                  <option key={p.value} value={p.value}>
                    {p.label}
                  </option>
                ))}
              </select>
            </div>
            <p className="jb-hint" style={{ margin: "8px 0 16px" }}>
              Leave both blank if you&rsquo;d rather not say — the advert will read
              &ldquo;Salary not stated&rdquo;.
            </p>

            <label className="jb-label">Type</label>
            <div className="jb-chips">
              {JOB_TYPES.map((t) => (
                <button
                  key={t.value}
                  type="button"
                  className={"jb-chip" + (type === t.value ? " on" : "")}
                  onClick={() => setType(t.value)}
                >
                  {t.label}
                </button>
              ))}
            </div>
          </section>

          <section className="jb-sec">
            <label className="jb-label">
              Screening questions <span className="jb-opt">optional, up to three</span>
            </label>

            {questions.map((q, i) => (
              <div key={i} className="jb-q">
                <div className="jb-qtop">
                  <input
                    className="jb-field"
                    value={q.title}
                    maxLength={256}
                    placeholder="What would you like to ask?"
                    onChange={(e) => setQuestion(i, { title: e.target.value })}
                  />
                  <select
                    className="jb-field"
                    value={q.type}
                    onChange={(e) =>
                      setQuestion(i, { type: e.target.value as JobQuestion["type"] })
                    }
                  >
                    <option value="text">Free text</option>
                    <option value="multiple_choice">Multiple choice</option>
                  </select>
                  <button
                    type="button"
                    className="jb-qdel"
                    onClick={() => setQuestions((qs) => qs.filter((_, n) => n !== i))}
                    aria-label="Remove this question"
                  >
                    <Trash2 size={15} />
                  </button>
                </div>

                {q.type === "multiple_choice" && (
                  <input
                    className="jb-field"
                    style={{ marginTop: 8 }}
                    value={(q.choices ?? []).join(", ")}
                    placeholder="Answers, separated by commas — Yes, No, Sometimes"
                    onChange={(e) =>
                      setQuestion(i, {
                        choices: e.target.value.split(",").map((c) => c.trim()),
                      })
                    }
                  />
                )}
              </div>
            ))}

            {questions.length < 3 && (
              <button
                type="button"
                className="jb-addq"
                onClick={() => setQuestions((qs) => [...qs, { type: "text", title: "" }])}
              >
                <Plus size={15} /> Add a question
              </button>
            )}
          </section>

          <section className="jb-sec">
            <label className="jb-label">
              Cover image <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) setCoverImage(await fileToDataUrl(file, 1200));
              }}
            />
            {coverImage && (
              // eslint-disable-next-line @next/next/no-img-element
              <img className="jb-cover" src={coverImage} alt="" />
            )}
          </section>

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

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