/** Daily check-in in plain English; maps calm labels onto backend enums. */

import { X } from "lucide-preact";
import { useEffect, useState } from "preact/hooks";
import {
  getDaily,
  putDaily,
  type DailyRow,
  type DailyUpsert,
  type PrimaryBrick,
  type ProofBrickKind,
} from "../api";
import { Button } from "../components/Button";
import { Pressable } from "../components/Pressable";
import { useToast } from "../components/Toast";
import { isoDate } from "../dates";

const EMPTY: DailyUpsert = {
  primary_brick: "none",
  brick_done: false,
  corn_sessions: 0,
  delay_ok: true,
  daydream: "none",
  rerun: "clean",
  court: "closed",
  stayed_indoors_all_day: false,
  left_room: false,
  left_home: false,
  movement_minutes: 0,
  interrupt_walk_minutes: 0,
  fantasy_walk_minutes: 0,
  headphones_on_walk: false,
  music_cinematic_on_walk: false,
  proof_brick_done: false,
  proof_brick_kind: null,
  fantasy_minutes_scheduled: 0,
  fantasy_minutes_unplanned: 0,
  note: "",
  win: "",
};

const PROOF_KINDS: { value: ProofBrickKind; label: string }[] = [
  { value: "interrupt_walk", label: "Interrupt walk" },
  { value: "body_or_room", label: "Body or room" },
  { value: "trip_admin", label: "Trip admin" },
  { value: "earn", label: "Earn" },
  { value: "boundary", label: "Boundary" },
  { value: "food", label: "Food" },
  { value: "survive", label: "Survive" },
  { value: "other", label: "Other" },
];

const BRICK_OPTIONS: { value: PrimaryBrick; label: string }[] = [
  { value: "A", label: "Admin / trip task" },
  { value: "B", label: "Body or room care" },
  { value: "C", label: "Work / skill" },
  { value: "D", label: "Home exit plan" },
  { value: "E", label: "Held a boundary" },
  { value: "S", label: "Just survived the day" },
  { value: "none", label: "Nothing yet" },
];

const DAYDREAM_OPTIONS: { value: DailyUpsert["daydream"]; label: string }[] = [
  { value: "none", label: "No" },
  { value: "done", label: "Yes, and I still did one real step" },
  { value: "fc", label: "Yes, and I didn’t do a real step" },
];

const RERUN_OPTIONS: { value: DailyUpsert["rerun"]; label: string }[] = [
  { value: "clean", label: "I cut it short or didn’t go there" },
  { value: "R", label: "I stayed stuck in it" },
];

const COURT_OPTIONS: { value: DailyUpsert["court"]; label: string }[] = [
  { value: "closed", label: "I closed it" },
  { value: "court", label: "I kept prosecuting the case" },
];

const TIP_KEY = "daily-tip-dismissed";

function ChoiceList<T extends string>({
  options,
  value,
  onChange,
}: {
  options: { value: T; label: string }[];
  value: T;
  onChange: (v: T) => void;
}) {
  return (
    <div class="choice-list" role="radiogroup">
      {options.map((option) => (
        <Pressable
          key={option.value}
          className="choice-item"
          ariaPressed={option.value === value}
          onClick={() => onChange(option.value)}
        >
          {option.label}
        </Pressable>
      ))}
    </div>
  );
}

function Stepper({
  value,
  onChange,
}: {
  value: number;
  onChange: (v: number) => void;
}) {
  return (
    <div class="stepper-row">
      <Pressable
        className="stepper-btn"
        ariaLabel="One less"
        disabled={value <= 0}
        onClick={() => onChange(Math.max(0, value - 1))}
      >
        −
      </Pressable>
      <strong class="stepper-value">{value >= 3 ? `${value}` : value}</strong>
      <Pressable
        className="stepper-btn"
        ariaLabel="One more"
        disabled={value >= 10}
        onClick={() => onChange(Math.min(10, value + 1))}
      >
        +
      </Pressable>
    </div>
  );
}

function friendlyDate(day: string): string {
  return new Date(`${day}T00:00:00`).toLocaleDateString(undefined, {
    weekday: "long",
    month: "long",
    day: "numeric",
  });
}

function breakdown(row: DailyRow): { label: string; earned: boolean; pts: number }[] {
  const cornOk =
    row.corn_sessions === 0 || (row.corn_sessions <= 1 && row.delay_ok);
  return [
    { label: "Did the main action", earned: row.brick_done, pts: 2 },
    {
      label: "No escapes — or just one, after waiting",
      earned: cornOk,
      pts: 1,
    },
    {
      label: "Fantasy didn’t replace a real step",
      earned: row.daydream !== "fc",
      pts: 1,
    },
    { label: "Cut the mental replay short", earned: row.rerun === "clean", pts: 1 },
    { label: "Kept the case closed", earned: row.court === "closed", pts: 1 },
  ];
}

export function Daily() {
  const toast = useToast();
  const [day, setDay] = useState(isoDate(new Date()));
  const [form, setForm] = useState<DailyUpsert>(EMPTY);
  const [saved, setSaved] = useState<DailyRow | null>(null);
  const [busy, setBusy] = useState(false);
  const [tipHidden, setTipHidden] = useState(
    () => localStorage.getItem(TIP_KEY) === "1",
  );

  const load = async (date: string) => {
    setSaved(null);
    try {
      const row = await getDaily(date);
      setForm({
        primary_brick: row.primary_brick,
        brick_done: row.brick_done,
        corn_sessions: row.corn_sessions,
        delay_ok: row.delay_ok,
        daydream: row.daydream,
        rerun: row.rerun,
        court: row.court,
        stayed_indoors_all_day: Boolean(row.stayed_indoors_all_day),
        left_room: Boolean(row.left_room),
        left_home: Boolean(row.left_home),
        movement_minutes: row.movement_minutes ?? 0,
        interrupt_walk_minutes: row.interrupt_walk_minutes ?? 0,
        fantasy_walk_minutes: row.fantasy_walk_minutes ?? 0,
        headphones_on_walk: Boolean(row.headphones_on_walk),
        music_cinematic_on_walk: Boolean(row.music_cinematic_on_walk),
        proof_brick_done: Boolean(row.proof_brick_done),
        proof_brick_kind: row.proof_brick_kind ?? null,
        fantasy_minutes_scheduled: row.fantasy_minutes_scheduled ?? 0,
        fantasy_minutes_unplanned: row.fantasy_minutes_unplanned ?? 0,
        note: row.note,
        win: row.win ?? "",
      });
      setSaved(row);
    } catch {
      setForm(EMPTY);
    }
  };

  useEffect(() => {
    void load(day);
  }, [day]);

  const save = async () => {
    setBusy(true);
    try {
      const row = await putDaily(day, form);
      setSaved(row);
      toast.show("Saved");
    } catch (e) {
      toast.show(e instanceof Error ? e.message : "Save failed", "error");
    } finally {
      setBusy(false);
    }
  };

  return (
    <div class="app-shell">
      <header class="top-bar material-bar daily-header">
        <div>
          <h1 class="page-title">Today</h1>
          <span class="daily-date">{friendlyDate(day)}</span>
        </div>
        <strong class="daily-points" aria-label="Points today">
          {saved ? `${saved.points}/6` : "–/6"}
        </strong>
      </header>
      <main class="page stack">
        {!tipHidden && (
          <div class="tip-card" role="note">
            <p>
              This page is your day’s scoreboard. Use <strong>Log</strong> for
              what happened and what you tried.
            </p>
            <Pressable
              className="tip-dismiss"
              ariaLabel="Dismiss tip"
              onClick={() => {
                localStorage.setItem(TIP_KEY, "1");
                setTipHidden(true);
              }}
            >
              <X size={16} />
            </Pressable>
          </div>
        )}

        <label class="field-label">
          Date
          <input
            class="field-input"
            type="date"
            value={day}
            onInput={(e) => setDay((e.target as HTMLInputElement).value)}
          />
        </label>

        <section class="surface-card form-card stack">
          <span class="section-title">What was today’s one real thing?</span>
          <ChoiceList
            options={BRICK_OPTIONS}
            value={form.primary_brick}
            onChange={(primary_brick) => setForm({ ...form, primary_brick })}
          />
          <label class="toggle-row">
            <span>I actually did this today</span>
            <input
              type="checkbox"
              checked={form.brick_done}
              onChange={(e) =>
                setForm({
                  ...form,
                  brick_done: (e.target as HTMLInputElement).checked,
                })
              }
            />
          </label>
        </section>

        <section class="surface-card form-card stack win-card">
          <span class="section-title">Today’s win</span>
          <p class="caption muted">
            One thing that went well — a real step, a kind moment, anything.
            Optional. This is the part that compounds.
          </p>
          <input
            class="field-input"
            type="text"
            placeholder="e.g. Walked a new route"
            value={form.win}
            onInput={(e) =>
              setForm({ ...form, win: (e.target as HTMLInputElement).value })
            }
          />
        </section>

        <section class="surface-card form-card stack">
          <span class="section-title">Escapes</span>
          <span class="field-label">
            How many times did you use porn/masturbation to escape today?
          </span>
          <Stepper
            value={form.corn_sessions}
            onChange={(corn_sessions) => setForm({ ...form, corn_sessions })}
          />
          {form.corn_sessions >= 1 && (
            <>
              <span class="field-label">
                Before that, did you wait about 10 minutes and do one small real
                task first?
              </span>
              <ChoiceList
                options={[
                  { value: "yes", label: "Yes" },
                  { value: "no", label: "No" },
                ]}
                value={form.delay_ok ? "yes" : "no"}
                onChange={(v) => setForm({ ...form, delay_ok: v === "yes" })}
              />
            </>
          )}
        </section>

        <p class="caption muted core-hint">
          Rough day? Just save the basics below — the extra detail can wait.
        </p>

        <Button className="btn-large" disabled={busy} onClick={save}>
          {busy ? "Saving…" : "Save the basics"}
        </Button>

        <details class="core-more">
          <summary>More detail (optional)</summary>
          <div class="core-more-body stack">

        <section class="surface-card form-card stack">
          <span class="section-title">Did you drift into fantasy today?</span>
          <ChoiceList
            options={DAYDREAM_OPTIONS}
            value={form.daydream}
            onChange={(daydream) => setForm({ ...form, daydream })}
          />
        </section>

        <section class="surface-card form-card stack">
          <span class="section-title">Replaying painful scenes?</span>
          <ChoiceList
            options={RERUN_OPTIONS}
            value={form.rerun}
            onChange={(rerun) => setForm({ ...form, rerun })}
          />
          <span class="section-title">Arguing the family case in your head?</span>
          <ChoiceList
            options={COURT_OPTIONS}
            value={form.court}
            onChange={(court) => setForm({ ...form, court })}
          />
        </section>

        <section class="surface-card form-card stack">
          <span class="section-title">Movement</span>
          <span class="field-label">Did you stay indoors the whole day?</span>
          <ChoiceList
            options={[
              { value: "yes", label: "Yes" },
              { value: "no", label: "No" },
            ]}
            value={form.stayed_indoors_all_day ? "yes" : "no"}
            onChange={(v) =>
              setForm({ ...form, stayed_indoors_all_day: v === "yes" })
            }
          />
          <span class="field-label">Did you leave the bedroom / room?</span>
          <ChoiceList
            options={[
              { value: "yes", label: "Yes" },
              { value: "no", label: "No" },
            ]}
            value={form.left_room ? "yes" : "no"}
            onChange={(v) => setForm({ ...form, left_room: v === "yes" })}
          />
          <span class="field-label">Did you leave the house/compound?</span>
          <ChoiceList
            options={[
              { value: "yes", label: "Yes" },
              { value: "no", label: "No" },
            ]}
            value={form.left_home ? "yes" : "no"}
            onChange={(v) => setForm({ ...form, left_home: v === "yes" })}
          />
          <label class="field-label">
            Interrupt walk minutes (attention break — better without headphones)
            <input
              class="field-input"
              type="number"
              min={0}
              max={24 * 60}
              value={form.interrupt_walk_minutes}
              onInput={(e) => {
                const interrupt_walk_minutes = Math.max(
                  0,
                  Number((e.target as HTMLInputElement).value) || 0,
                );
                setForm({
                  ...form,
                  interrupt_walk_minutes,
                  movement_minutes:
                    interrupt_walk_minutes + form.fantasy_walk_minutes,
                });
              }}
            />
          </label>
          <label class="field-label">
            Fantasy / music walk minutes (honest log OK)
            <input
              class="field-input"
              type="number"
              min={0}
              max={24 * 60}
              value={form.fantasy_walk_minutes}
              onInput={(e) => {
                const fantasy_walk_minutes = Math.max(
                  0,
                  Number((e.target as HTMLInputElement).value) || 0,
                );
                setForm({
                  ...form,
                  fantasy_walk_minutes,
                  movement_minutes:
                    form.interrupt_walk_minutes + fantasy_walk_minutes,
                });
              }}
            />
          </label>
          <span class="field-label">Headphones on a walk?</span>
          <ChoiceList
            options={[
              { value: "yes", label: "Yes" },
              { value: "no", label: "No" },
            ]}
            value={form.headphones_on_walk ? "yes" : "no"}
            onChange={(v) => setForm({ ...form, headphones_on_walk: v === "yes" })}
          />
          <span class="field-label">Cinematic / movie music on a walk?</span>
          <ChoiceList
            options={[
              { value: "yes", label: "Yes" },
              { value: "no", label: "No" },
            ]}
            value={form.music_cinematic_on_walk ? "yes" : "no"}
            onChange={(v) =>
              setForm({ ...form, music_cinematic_on_walk: v === "yes" })
            }
          />
          <p class="caption muted">
            Compound laps and short walks count — no spend needed. Total moving:{" "}
            {form.interrupt_walk_minutes + form.fantasy_walk_minutes}m
          </p>
        </section>

        <section class="surface-card form-card stack">
          <span class="section-title">Proof brick</span>
          <span class="field-label">Did you do one real proof step today?</span>
          <ChoiceList
            options={[
              { value: "yes", label: "Yes" },
              { value: "no", label: "No" },
            ]}
            value={form.proof_brick_done ? "yes" : "no"}
            onChange={(v) =>
              setForm({
                ...form,
                proof_brick_done: v === "yes",
                proof_brick_kind: v === "yes" ? form.proof_brick_kind : null,
              })
            }
          />
          {form.proof_brick_done && (
            <>
              <span class="field-label">What kind?</span>
              <ChoiceList
                options={PROOF_KINDS}
                value={(form.proof_brick_kind || "other") as ProofBrickKind}
                onChange={(proof_brick_kind) =>
                  setForm({ ...form, proof_brick_kind })
                }
              />
            </>
          )}
        </section>

        <section class="surface-card form-card stack">
          <span class="section-title">Movie / fantasy time</span>
          <label class="field-label">
            Minutes in a scheduled slot
            <input
              class="field-input"
              type="number"
              min={0}
              max={24 * 60}
              value={form.fantasy_minutes_scheduled}
              onInput={(e) =>
                setForm({
                  ...form,
                  fantasy_minutes_scheduled: Math.max(
                    0,
                    Number((e.target as HTMLInputElement).value) || 0,
                  ),
                })
              }
            />
          </label>
          <label class="field-label">
            Minutes unplanned (drifted into it)
            <input
              class="field-input"
              type="number"
              min={0}
              max={24 * 60}
              value={form.fantasy_minutes_unplanned}
              onInput={(e) =>
                setForm({
                  ...form,
                  fantasy_minutes_unplanned: Math.max(
                    0,
                    Number((e.target as HTMLInputElement).value) || 0,
                  ),
                })
              }
            />
          </label>
          <p class="caption muted">Containment beats guilt. Log honestly.</p>
        </section>

          </div>
        </details>

        <label class="field-label">
          Note (optional)
          <input
            class="field-input"
            type="text"
            placeholder="One line about today"
            value={form.note}
            onInput={(e) =>
              setForm({ ...form, note: (e.target as HTMLInputElement).value })
            }
          />
        </label>

        {saved && (
          <section class="surface-card form-card stack">
            <span class="section-title">Points: {saved.points}/6</span>
            <ul class="points-breakdown">
              {breakdown(saved).map((item) => (
                <li key={item.label} class={item.earned ? "earned" : "missed"}>
                  <span>{item.label}</span>
                  <span class="points-pts">
                    {item.earned ? `+${item.pts}` : "0"}
                  </span>
                </li>
              ))}
            </ul>
          </section>
        )}

        <details class="how-points surface-card">
          <summary>How points work</summary>
          <ul>
            <li>Doing your one real thing earns 2 points.</li>
            <li>
              No escape sessions — or a single one after the 10-minute wait —
              earns 1 point.
            </li>
            <li>Fantasy is fine if you still did a real step: 1 point.</li>
            <li>Cutting mental replays short earns 1 point.</li>
            <li>Keeping the family case closed earns 1 point.</li>
          </ul>
        </details>

        <div class="daily-sticky">
          <Button className="btn-large" disabled={busy} onClick={save}>
            {busy ? "Saving…" : "Save today’s check-in"}
          </Button>
        </div>
      </main>
    </div>
  );
}
