/* Firecamp.jsx — CR #325: Fire Prevention Play video submissions + voting (/#firecamp)
   Sites upload their performance to YouTube, Google Drive, or OneDrive, submit the link
   with their PPR district + site name, and the video embeds below for voting.
   Vote tallies are dashboard-only (Fire Voting tab) — the public page never
   shows counts. Votes dedup server-side per device; localStorage greys out
   the button after voting. */

// CR #338: JJ extended the district selector to cover all 12 PPR districts.
const FIRECAMP_DISTRICTS = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
const FIRE_VOTES_LS_KEY = "ppr_fire_votes";
// CR #344: one vote per device per day. The stored record is stamped with the
// UTC day; a record from a prior day is ignored so the buttons re-enable.
// Matches the server, which folds the same UTC day into the dedup hash.
const fireVoteDay = () => new Date().toISOString().slice(0, 10);

function readFireVotes() {
  try {
    const o = JSON.parse(localStorage.getItem(FIRE_VOTES_LS_KEY) || "{}") || {};
    return (o.day === fireVoteDay() && o.voted) ? o.voted : {};
  } catch (e) { return {}; }
}

function FirecampPage() {
  const blank = { district: "", siteName: "", videoUrl: "" };
  const [data, setData] = React.useState(blank);
  const [submitted, setSubmitted] = React.useState(null);
  const [submitting, setSubmitting] = React.useState(false);
  const [error, setError] = React.useState("");
  const [videos, setVideos] = React.useState([]);
  const [loadingVideos, setLoadingVideos] = React.useState(true);
  const [voted, setVoted] = React.useState(readFireVotes);
  const update = (k, v) => setData(d => ({ ...d, [k]: v }));

  const loadVideos = React.useCallback(() => {
    fetch("/api/data/firecamp")
      .then(r => r.json())
      .then(j => setVideos(j.rows || []))
      .catch(() => {})
      .finally(() => setLoadingVideos(false));
  }, []);
  React.useEffect(() => { loadVideos(); }, [loadVideos]);

  const onSubmit = async (e) => {
    e.preventDefault();
    setSubmitting(true);
    setError("");
    try {
      const res = await fetch("/api/data/firecamp", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          action: "submit",
          district: Number(data.district),
          site_name: data.siteName,
          video_url: data.videoUrl,
        })
      });
      const json = await res.json().catch(() => ({}));
      if (!res.ok || !json.ok) throw new Error(json.error || `error_${res.status}`);
      setSubmitted({ ref: json.ref });
      loadVideos();
    } catch (err) {
      const code = String(err && err.message || "");
      setError(
        code === "already_submitted" ? "That video has already been submitted — it should be playing below."
        : code === "bad_video_url" ? "That link doesn't look like a YouTube, Google Drive, or OneDrive video link. Copy the share link straight from the app and try again."
        : code === "rate_limited" ? "Too many submissions from this connection — wait a few minutes and try again."
        : "Couldn't send right now. Please try again, or email Joseph.J.Pospiech@phila.gov."
      );
    } finally {
      setSubmitting(false);
    }
  };

  const onVote = async (videoId) => {
    if (voted[videoId]) return;
    // Optimistic: grey the button immediately; the server dedups per device
    // anyway, so a failed request just means the vote silently didn't count.
    const next = { ...voted, [videoId]: true };
    setVoted(next);
    try { localStorage.setItem(FIRE_VOTES_LS_KEY, JSON.stringify({ day: fireVoteDay(), voted: next })); } catch (e) {}
    try {
      await fetch("/api/data/firecamp", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action: "vote", video_id: videoId })
      });
    } catch (e) {}
  };

  // Group live videos by district for the watch + vote section.
  const byDistrict = videos.reduce((acc, v) => {
    (acc[v.district] = acc[v.district] || []).push(v);
    return acc;
  }, {});
  const districtsWithVideos = Object.keys(byDistrict).map(Number).sort((a, b) => a - b);

  return (
    <div>
      <FormHero
        eyebrow="Fire Prevention Play"
        title={<>Put your site's<br/>play on stage.</>}
        body="Rec sites across Philadelphia are performing the Fire Prevention Play. Record your site's performance, upload it to YouTube, Google Drive, or OneDrive using the steps below, and submit the link. Your video appears on this page for the citywide vote."
        bg="var(--c-primary)"
        logo={{ src: "/img/fire-dept-logo.png", alt: "Philadelphia Fire Department" }}
      />

      {/* RULES + IMPORTANT DATES (CR #344) — sit above the submission steps */}
      <section className="section" style={{ paddingBottom: 0 }}>
        <div className="container" style={{ maxWidth: 920 }}>
          <div className="eyebrow">Before you submit</div>
          <h2 className="display" style={{ fontSize: "clamp(28px, 4.5vw, 44px)", margin: "10px 0 24px" }}>
            The rules.
          </h2>
          <div className="card">
            <ol style={{ paddingLeft: 22, fontSize: 14.5, lineHeight: 1.7, display: "flex", flexDirection: "column", gap: 12, margin: 0 }}>
              <li>The performers must be 12 years of age and under.</li>
              <li>There is no restriction to the number of participants.</li>
              <li>No actual fires may be used. All fires must be simulated! No combustibles are permitted.</li>
              <li>All scripts must be original and developed by this year's participants.</li>
              <li>Each play must be longer than two minutes, but not longer than six minutes. If a play is under two minutes, ten points will be deducted from their cumulative total. If a play is over six minutes, ten points will be deducted from the cumulative total.</li>
              <li>Only one full performance can be considered for judging.</li>
              <li>The best representative play from each district will be selected to compete at the citywide level. All videos will be displayed and submitted on phillyperforms.com.</li>
              <li>The decision of the judges is final.</li>
            </ol>
          </div>

          <div className="eyebrow" style={{ marginTop: 40 }}>Important dates</div>
          <h2 className="display" style={{ fontSize: "clamp(28px, 4.5vw, 44px)", margin: "10px 0 24px" }}>
            Mark your calendar.
          </h2>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(190px, 1fr))", gap: 18 }}>
            <div className="card">
              <div className="chip" style={{ marginBottom: 12 }}>Submit by</div>
              <div className="display" style={{ fontSize: 26, margin: "0 0 4px" }}>July 22</div>
              <div style={{ fontSize: 14, color: "var(--c-ink-soft)" }}>All videos must be submitted.</div>
            </div>
            <div className="card">
              <div className="chip" style={{ marginBottom: 12 }}>District winners</div>
              <div className="display" style={{ fontSize: 26, margin: "0 0 4px" }}>July 24</div>
              <div style={{ fontSize: 14, color: "var(--c-ink-soft)" }}>One play selected per district.</div>
            </div>
            <div className="card">
              <div className="chip" style={{ marginBottom: 12 }}>Citywide competition</div>
              <div className="display" style={{ fontSize: 26, margin: "0 0 4px" }}>July 31</div>
              <div style={{ fontSize: 14, color: "var(--c-ink-soft)" }}>The Free Library, 1901 Vine Street.</div>
            </div>
          </div>
        </div>
      </section>

      {/* HOW TO UPLOAD */}
      <section className="section" style={{ paddingBottom: 0 }}>
        <div className="container" style={{ maxWidth: 920 }}>
          <div className="eyebrow">Step 1 — Upload your video</div>
          <h2 className="display" style={{ fontSize: "clamp(28px, 4.5vw, 44px)", margin: "10px 0 24px" }}>
            From your phone, three easy ways.
          </h2>
          <div className="fg-3" style={{ gap: 18 }}>
            <div className="card">
              <div className="chip" style={{ marginBottom: 12 }}>Option A — YouTube</div>
              <ol style={{ paddingLeft: 20, fontSize: 14.5, lineHeight: 1.65, display: "flex", flexDirection: "column", gap: 8, margin: 0 }}>
                <li>Open the <strong>YouTube</strong> app and sign in.</li>
                <li>Tap the <strong>+</strong> button at the bottom, then <strong>Upload a video</strong>.</li>
                <li>Pick your recording and give it a title (your site name works great).</li>
                <li>Set visibility to <strong>Public</strong> or <strong>Unlisted</strong> — <em>not Private</em>, or it won't play here.</li>
                <li>Once it finishes uploading, tap <strong>Share → Copy link</strong>.</li>
              </ol>
            </div>
            <div className="card">
              <div className="chip" style={{ marginBottom: 12 }}>Option B — Google Drive</div>
              <ol style={{ paddingLeft: 20, fontSize: 14.5, lineHeight: 1.65, display: "flex", flexDirection: "column", gap: 8, margin: 0 }}>
                <li>Open the <strong>Google Drive</strong> app.</li>
                <li>Tap <strong>+ New → Upload</strong> and pick your recording.</li>
                <li>After it uploads, tap the <strong>⋮</strong> menu next to the file, then <strong>Share</strong>.</li>
                <li>Under General access, choose <strong>"Anyone with the link"</strong> — otherwise it won't play here.</li>
                <li>Tap <strong>Copy link</strong>.</li>
              </ol>
            </div>
            <div className="card">
              <div className="chip" style={{ marginBottom: 12 }}>Option C — OneDrive</div>
              <ol style={{ paddingLeft: 20, fontSize: 14.5, lineHeight: 1.65, display: "flex", flexDirection: "column", gap: 8, margin: 0 }}>
                <li>Open the <strong>OneDrive</strong> app and sign in.</li>
                <li>Tap <strong>+ → Upload</strong> and pick your recording.</li>
                <li>After it uploads, tap the <strong>⋯</strong> menu next to the file, then <strong>Share</strong>.</li>
                <li>Set the link to <strong>"Anyone with the link can view"</strong> — otherwise it won't open here.</li>
                <li>Tap <strong>Copy link</strong>.</li>
              </ol>
            </div>
          </div>
          <p style={{ fontSize: 13.5, color: "var(--c-ink-soft)", marginTop: 14 }}>
            Then paste the copied link into the form below. Questions? Email{" "}
            <a href="mailto:Joseph.J.Pospiech@phila.gov">Joseph.J.Pospiech@phila.gov</a>.
          </p>
        </div>
      </section>

      {/* SUBMIT FORM */}
      <section className="section">
        <div className="container" style={{ maxWidth: 920 }}>
          <div className="eyebrow">Step 2 — Submit your link</div>
          <h2 className="display" style={{ fontSize: "clamp(28px, 4.5vw, 44px)", margin: "10px 0 24px" }}>
            Enter your site for the vote.
          </h2>
          {submitted ? (
            <div className="card" style={{ textAlign: "center", padding: 36 }}>
              <div style={{ fontSize: 48, marginBottom: 10 }}>✦</div>
              <h3 className="display" style={{ fontSize: 28, marginBottom: 10 }}>Got it — your video is in.</h3>
              <p style={{ fontSize: 15, color: "var(--c-ink-soft)", lineHeight: 1.55, maxWidth: 520, margin: "0 auto 20px" }}>
                It's live in the voting section below. Reference: {submitted.ref}. Share this page with
                your families so they can vote for your site.
              </p>
              <button className="btn secondary" onClick={() => { setSubmitted(null); setData(blank); }}>
                Submit another video
              </button>
            </div>
          ) : (
            <form onSubmit={onSubmit} className="card" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
              <Row>
                <Field
                  label="Your PPR district"
                  type="select"
                  options={[""].concat(FIRECAMP_DISTRICTS)}
                  optionLabels={["—"].concat(FIRECAMP_DISTRICTS.map(d => `District ${d}`))}
                  value={data.district}
                  onChange={v => update("district", v)}
                  required
                />
                <Field label="Site name" value={data.siteName} onChange={v => update("siteName", v)} required placeholder="e.g. Athletic Recreation Center" />
              </Row>
              <Field
                label="Video link (YouTube, Google Drive, or OneDrive)"
                value={data.videoUrl}
                onChange={v => update("videoUrl", v)}
                required
                placeholder="Paste your YouTube, Google Drive, or OneDrive link"
              />
              {error && <p style={{ color: "var(--c-primary-deep)", fontSize: 14, margin: 0 }}>{error}</p>}
              <div>
                <button type="submit" className="btn" disabled={submitting || !data.district || !data.siteName.trim() || !data.videoUrl.trim()}>
                  {submitting ? "Submitting…" : "Submit video"}
                </button>
              </div>
            </form>
          )}
        </div>
      </section>

      {/* WATCH + VOTE */}
      <section className="section" style={{ background: "var(--c-cream-deep)", borderTop: "2px solid var(--c-ink)" }}>
        <div className="container">
          <div className="eyebrow">Step 3 — Watch &amp; vote</div>
          <h2 className="display" style={{ fontSize: "clamp(28px, 4.5vw, 44px)", margin: "10px 0 8px" }}>
            The performances, by district.
          </h2>
          <p style={{ fontSize: 14.5, color: "var(--c-ink-soft)", maxWidth: 640, lineHeight: 1.55, marginBottom: 28 }}>
            One vote per video per device. Results are tallied by the Performing Arts Office at the
            end of the voting period.
          </p>

          {loadingVideos ? (
            <p style={{ color: "var(--c-ink-soft)", fontSize: 14 }}>Loading videos…</p>
          ) : districtsWithVideos.length === 0 ? (
            <div className="card" style={{ textAlign: "center", padding: 36 }}>
              <p style={{ fontSize: 15, color: "var(--c-ink-soft)", margin: 0 }}>
                No videos yet — yours could be the first. Submit above.
              </p>
            </div>
          ) : (
            districtsWithVideos.map(d => (
              <div key={d} style={{ marginBottom: 40 }}>
                <div style={{ display: "flex", alignItems: "baseline", gap: 12, marginBottom: 16, borderBottom: "2px solid var(--c-ink)", paddingBottom: 10 }}>
                  <h3 className="display" style={{ fontSize: 26, margin: 0 }}>District {d}</h3>
                  <span className="chip">{byDistrict[d].length} {byDistrict[d].length === 1 ? "video" : "videos"}</span>
                </div>
                <div className="fg-2" style={{ gap: 18 }}>
                  {byDistrict[d].map(v => (
                    <div key={v.id} className="card" style={{ padding: 0, overflow: "hidden" }}>
                      {v.video_kind === "onedrive" ? (
                        <a
                          href={v.video_id}
                          target="_blank"
                          rel="noopener noreferrer"
                          title={`${v.site_name} — Fire Prevention Play`}
                          style={{ position: "relative", display: "block", paddingTop: "56.25%", background: "var(--c-ink)", textDecoration: "none" }}
                        >
                          <span style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 8, color: "#f6f1ea", textAlign: "center", padding: 16 }}>
                            <span style={{ fontSize: 40, lineHeight: 1 }}>▶</span>
                            <span style={{ fontWeight: 600, fontSize: 15 }}>Watch on OneDrive</span>
                            <span style={{ fontSize: 12.5, opacity: 0.75 }}>Opens in a new tab</span>
                          </span>
                        </a>
                      ) : (
                        <div style={{ position: "relative", paddingTop: "56.25%", background: "var(--c-ink)" }}>
                          <iframe
                            src={v.video_kind === "drive"
                              ? `https://drive.google.com/file/d/${v.video_id}/preview`
                              : `https://www.youtube-nocookie.com/embed/${v.video_id}?rel=0&modestbranding=1`}
                            title={`${v.site_name} — Fire Prevention Play`}
                            style={{ position: "absolute", inset: 0, width: "100%", height: "100%", border: 0 }}
                            loading="lazy"
                            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                            allowFullScreen
                          />
                        </div>
                      )}
                      <div style={{ padding: "16px 18px", display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
                        <div style={{ fontWeight: 600, fontSize: 15 }}>{v.site_name}</div>
                        {voted[v.id] ? (
                          <button className="btn secondary small" disabled style={{ opacity: 0.7, cursor: "default" }}>✓ Voted</button>
                        ) : (
                          <button className="btn small" onClick={() => onVote(v.id)}>Vote for this site</button>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
            ))
          )}
        </div>
      </section>
    </div>
  );
}

Object.assign(window, { FirecampPage });
