import { useRef, useState } from "react";

import { deriveYearAndTerm, formatEventDate, generateRequestId, slugify } from "../lib/eventPayload";

const BACKEND_URL = process.env.NEXT_PUBLIC_BACKEND_URL ?? "http://localhost:8001";

interface FormState {
  submittedByEmail: string;
  name: string;
  short: string;
  startLocal: string;
  endLocal: string;
  online: boolean;
  location: string;
  descriptionMarkdown: string;
  registerLink: string;
}

const initialState: FormState = {
  submittedByEmail: "",
  name: "",
  short: "",
  startLocal: "",
  endLocal: "",
  online: false,
  location: "",
  descriptionMarkdown: "",
  registerLink: "",
};

type SubmitResult =
  | { kind: "success"; body: unknown }
  | { kind: "error"; message: string }
  | null;

interface UploadedPoster {
  sourceUrl: string;
  filename: string;
  contentType: string;
}

export default function Home() {
  const [form, setForm] = useState<FormState>(initialState);
  const [posterFile, setPosterFile] = useState<File | null>(null);
  const [submitting, setSubmitting] = useState(false);
  const [result, setResult] = useState<SubmitResult>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  function update<K extends keyof FormState>(key: K, value: FormState[K]) {
    setForm((prev) => ({ ...prev, [key]: value }));
  }

  async function uploadPoster(file: File): Promise<UploadedPoster> {
    const body = new FormData();
    body.append("poster", file);
    const response = await fetch(`${BACKEND_URL}/api/dev-uploads`, { method: "POST", body });
    const uploaded = await response.json();
    if (!response.ok) {
      throw new Error(uploaded?.error?.message ?? "Poster upload failed");
    }
    return uploaded;
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();

    // Mirrors the legacy Eventer app's client-side checks (public/client.js):
    // required fields are already enforced by the `required` attributes below,
    // this covers the one thing HTML validation can't: end >= start.
    if (form.endLocal && new Date(form.endLocal).getTime() < new Date(form.startLocal).getTime()) {
      alert("The end date and time must be after the start date and time.");
      return;
    }

    if (!confirm("You are about to submit this event. Continue?")) {
      return;
    }

    setSubmitting(true);
    setResult(null);

    try {
      let poster: UploadedPoster | null = null;
      if (posterFile) {
        poster = await uploadPoster(posterFile);
      }

      const slug = slugify(form.name);
      const { year, term } = deriveYearAndTerm(form.startLocal);

      const payload = {
        requestId: generateRequestId(slug),
        submittedByEmail: form.submittedByEmail,
        event: {
          name: form.name,
          short: form.short,
          startDate: formatEventDate(form.startLocal),
          endDate: form.endLocal ? formatEventDate(form.endLocal) : null,
          online: form.online,
          location: form.location,
          descriptionMarkdown: form.descriptionMarkdown,
          registerLink: form.registerLink || null,
          year,
          term,
          slug,
          poster,
        },
      };

      const response = await fetch(`${BACKEND_URL}/api/events/publish`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      const responseBody = await response.json();
      if (response.ok) {
        setResult({ kind: "success", body: responseBody });
        setForm(initialState);
        setPosterFile(null);
        if (fileInputRef.current) {
          fileInputRef.current.value = "";
        }
      } else {
        setResult({ kind: "error", message: JSON.stringify(responseBody, null, 2) });
      }
    } catch (error) {
      setResult({ kind: "error", message: error instanceof Error ? error.message : String(error) });
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <main>
      <h1>EventCentral — v1 prototype</h1>
      <p className="hint">
        This form calls the EventCentral backend directly, standing in for the real upstream backend
        described in the integration contract (which doesn&apos;t exist yet). The upstream-service secret
        is disabled in v1, but submitters are still checked against an allowlist, same as the legacy
        Eventer app.
      </p>

      <form onSubmit={handleSubmit}>
        <div className="field">
          <label htmlFor="submittedByEmail">Your @uwaterloo.ca email</label>
          <input
            id="submittedByEmail"
            type="email"
            required
            value={form.submittedByEmail}
            onChange={(e) => update("submittedByEmail", e.target.value)}
          />
        </div>

        <div className="field">
          <label htmlFor="name">Event name</label>
          <input id="name" required value={form.name} onChange={(e) => update("name", e.target.value)} />
        </div>

        <div className="field">
          <label htmlFor="short">Short description</label>
          <input id="short" required value={form.short} onChange={(e) => update("short", e.target.value)} />
        </div>

        <div className="row">
          <div className="field">
            <label htmlFor="start">Start</label>
            <input
              id="start"
              type="datetime-local"
              required
              value={form.startLocal}
              onChange={(e) => update("startLocal", e.target.value)}
            />
          </div>
          <div className="field">
            <label htmlFor="end">End (optional)</label>
            <input
              id="end"
              type="datetime-local"
              value={form.endLocal}
              onChange={(e) => update("endLocal", e.target.value)}
            />
          </div>
        </div>

        <div className="field">
          <label>
            <input
              type="checkbox"
              checked={form.online}
              onChange={(e) => update("online", e.target.checked)}
            />{" "}
            Online event
          </label>
        </div>

        <div className="field">
          <label htmlFor="location">Location</label>
          <input
            id="location"
            required
            placeholder={form.online ? "Online" : "e.g. DC 1351"}
            value={form.location}
            onChange={(e) => update("location", e.target.value)}
          />
        </div>

        <div className="field">
          <label htmlFor="description">Description (Markdown)</label>
          <textarea
            id="description"
            required
            rows={6}
            value={form.descriptionMarkdown}
            onChange={(e) => update("descriptionMarkdown", e.target.value)}
          />
        </div>

        <div className="field">
          <label htmlFor="registerLink">Registration link (optional, https://)</label>
          <input
            id="registerLink"
            value={form.registerLink}
            onChange={(e) => update("registerLink", e.target.value)}
          />
        </div>

        <div className="field">
          <label htmlFor="poster">Event poster (optional, square-ish JPEG/PNG, max 15MB)</label>
          <input
            id="poster"
            ref={fileInputRef}
            type="file"
            accept="image/png,image/jpeg"
            onChange={(e) => setPosterFile(e.target.files?.[0] ?? null)}
          />
        </div>

        <button type="submit" disabled={submitting}>
          {submitting ? "Submitting…" : "Submit event"}
        </button>
      </form>

      {result && (
        <div className={`result ${result.kind === "success" ? "success" : "error"}`}>
          {result.kind === "success" ? JSON.stringify(result.body, null, 2) : result.message}
        </div>
      )}
    </main>
  );
}
