"use client";

/**
 * MobileWaterLogForm — measurement entry screen.
 *
 * Visual structure (Apple HIG form):
 *   - Sticky top nav: back chevron + "Log Reading" title.
 *   - Sticky headgate card under the nav — picks a tap target
 *     bigger than the iOS minimum (44pt) and lets the user confirm
 *     which headgate they're logging against at a glance.
 *   - Section: MEASUREMENT
 *       - HUGE numeric input (44pt font) — the visual focus of the
 *         screen. `inputMode="decimal"` brings up the iOS numeric
 *         keyboard with the decimal key.
 *       - Segmented control for units (CFS / GPM / gal / ac-in /
 *         ac-ft). The default selection is the headgate's configured
 *         unit.
 *       - Live "thresholds" hint below the input (e.g. "Normal range:
 *         2–8 CFS").
 *   - Section: TIMESTAMP (read-only, auto-updating every second so
 *     the user can verify they're logging against "now").
 *   - Section: NOTES (optional, 500-char multiline).
 *   - Sticky submit bar at the bottom — green primary button per
 *     HIG success semantics. Slides up out of the keyboard's way
 *     because the bar is `position: sticky; bottom: 0`.
 */
import {
  useEffect,
  useMemo,
  useRef,
  useState,
  type FormEvent,
} from "react";
import { SegmentedControl } from "./SegmentedControl";
import type { FieldHeadgate, MobileUnit } from "./types";
import { isIntegerUnit, MOBILE_UNITS } from "./types";
import { ChevronLeft, Clock, Gauge, Logout, Pencil, Pin, Spinner } from "./icons";
import {
  formatLongTimestamp,
  formatMeasurement,
  formatUnit,
  headgateSubtitle,
} from "./format";
import { useLang } from "@/lib/water-log/lang-context";

type Props = {
  headgate: FieldHeadgate;
  irrigatorName?: string;
  onSubmit: (input: { measurement: number; unit: string; notes: string }) => Promise<void>;
  onChangeHeadgate: () => void;
  onLogout: () => void;
  /** Optional preset units — defaults to MOBILE_UNITS. */
  units?: ReadonlyArray<MobileUnit | string>;
};

const NOTES_MAX = 500;

export function MobileWaterLogForm({
  headgate,
  irrigatorName,
  onSubmit,
  onChangeHeadgate,
  onLogout,
  units = MOBILE_UNITS,
}: Props) {
  const { t, lang } = useLang();
  // ── State ────────────────────────────────────────────────────────
  const [measurement, setMeasurement] = useState("");
  // Unit priority: most-recent log > headgate's static config > first
  // option. `last_unit` is the operator's *last* choice on this gate
  // across the whole fleet — far better than re-picking every shift.
  const [unit, setUnit] = useState<string>(() => {
    const remembered = headgate.last_unit;
    if (remembered && units.includes(remembered)) return remembered;
    if (units.includes(headgate.unit)) return headgate.unit;
    return units[0];
  });
  const [notes, setNotes] = useState("");
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [now, setNow] = useState<Date>(() => new Date());
  const measurementRef = useRef<HTMLInputElement>(null);

  // True when the current unit is an integer count (e.g. "holes").
  // Drives the input's keyboard + step constraint + the recap
  // formatting on the success screen.
  const integerUnit = isIntegerUnit(unit);

  // ── Auto-focus the measurement input on mount so the keyboard
  //    rises immediately.
  useEffect(() => {
    const t = window.setTimeout(() => measurementRef.current?.focus(), 80);
    return () => window.clearTimeout(t);
  }, []);

  // ── Live clock — re-renders every second. The setInterval is
  //    cheap (one DOM update per second on a hidden element) and
  //    gives the user confidence the timestamp reflects "now".
  useEffect(() => {
    const id = window.setInterval(() => setNow(new Date()), 1000);
    return () => window.clearInterval(id);
  }, []);

  // ── Threshold hint derived from the headgate. ────────────────────
  const thresholdHint = useMemo(() => {
    const h = headgate.high_threshold;
    const l = headgate.low_threshold;
    const u = formatUnit(unit, lang);
    if (h == null && l == null) return null;
    if (h != null && l != null) {
      return t.log.normalRange(l, h, u);
    }
    if (h != null) return t.log.alertAbove(h, u);
    // TS narrowing: reaching this line means `h == null && l != null`.
    return t.log.alertBelow(l as number, u);
  }, [headgate, unit, lang, t]);

  const submitted = (e?: FormEvent) => {
    e?.preventDefault();
    if (submitting) return;
    const value = parseFloat(measurement);
    if (!Number.isFinite(value) || value < 0) {
      setError(t.log.measurementError);
      return;
    }
    // Integer-count units (holes) reject fractional values — you
    // can't have 2.5 holes.
    if (integerUnit && !Number.isInteger(value)) {
      setError(t.log.measurementError);
      return;
    }
    if (value > 1_000_000) {
      setError(t.log.implausiblyLarge);
      return;
    }
    setSubmitting(true);
    setError(null);
    onSubmit({ measurement: value, unit, notes })
      .catch((err) => {
        setError(
          err instanceof Error ? err.message : t.log.submitting,
        );
        setSubmitting(false);
      });
    // On success the parent swaps to the success screen.
  };

  const subtitle = headgateSubtitle(headgate, lang);
  const unitLabel = formatUnit(unit, lang);
  // Disable submit when the value wouldn't survive `submitted()`'s
  // validation — including "holes" rejecting fractional values so
  // the button stays grey until the user types a valid integer.
  const parsed = parseFloat(measurement);
  const canSubmit =
    measurement.trim().length > 0 &&
    Number.isFinite(parsed) &&
    parsed >= 0 &&
    (!integerUnit || Number.isInteger(parsed)) &&
    !submitting;

  return (
    <div
      className="flex h-full flex-col bg-[#F2F2F7]"
      style={{
        paddingTop: "env(safe-area-inset-top)",
      }}
    >
      {/* ── Top nav ────────────────────────────────────────────── */}
      <header
        className="sticky top-0 z-30 flex items-center gap-2 border-b border-[rgba(60,60,67,0.12)] bg-[rgba(255,255,255,0.85)] px-2 py-2"
        style={{
          paddingTop: "calc(env(safe-area-inset-top) + 4px)",
          backdropFilter: "blur(20px) saturate(180%)",
          WebkitBackdropFilter: "blur(20px) saturate(180%)",
        }}
      >
        <button
          type="button"
          onClick={onChangeHeadgate}
          aria-label={t.common.a11yBackToHeadgates}
          className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-[#14532d] active:bg-[rgba(120,120,128,0.16)]"
        >
          <ChevronLeft size={22} />
        </button>

        <div className="min-w-0 flex-1">
          <h1
            className="truncate text-[17px] font-semibold leading-[1.15] text-[#1d1d1f]"
            style={{
              fontFamily:
                "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
            }}
          >
            {t.log.title}
          </h1>
          {irrigatorName ? (
            <div className="mt-0.5 flex items-center gap-1.5 truncate text-[12px] text-[rgba(60,60,67,0.6)]">
              <span
                aria-hidden
                className="inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full bg-[#14532d] text-[9px] font-bold uppercase text-white"
              >
                {initials(irrigatorName)}
              </span>
              <span className="truncate">{irrigatorName}</span>
            </div>
          ) : null}
        </div>

        <button
          type="button"
          onClick={onLogout}
          aria-label={t.common.a11ySignOut}
          className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-[#14532d] active:bg-[rgba(120,120,128,0.16)]"
        >
          <Logout size={20} />
        </button>
      </header>

      {/* ── Scrollable form body ───────────────────────────────── */}
      <form
        onSubmit={submitted}
        className="flex flex-1 flex-col"
        // Allow the form to grow so the sticky submit bar can sit at
        // the bottom on tall viewports.
      >
        <div className="flex-1 overflow-y-auto px-4 pb-[max(env(safe-area-inset-bottom),1rem)] pt-3">
          {/* ── Headgate summary card (sticky) ──────────────── */}
          <button
            type="button"
            onClick={onChangeHeadgate}
            aria-label={t.common.a11yChangeHeadgate}
            className="mb-5 flex w-full items-center gap-3 rounded-[14px] bg-white p-3 text-left active:bg-[rgba(120,120,128,0.10)]"
            style={{
              boxShadow: "0 1px 2px rgba(0,0,0,0.04), 0 1px 0 rgba(0,0,0,0.02)",
            }}
          >
            <div className="flex h-11 w-11 shrink-0 items-center justify-center rounded-[10px] bg-[rgba(20,83,45,0.10)] text-[#14532d]">
              <Gauge size={22} />
            </div>
            <div className="min-w-0 flex-1">
              <div
                className="truncate text-[17px] font-semibold leading-[1.2] text-[#1d1d1f]"
                style={{
                  fontFamily:
                    "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
                }}
              >
                {headgate.name}
              </div>
              <div className="mt-0.5 flex items-center gap-1.5 text-[13px] text-[rgba(60,60,67,0.6)]">
                <Pin size={12} className="shrink-0 opacity-60" />
                <span className="truncate">{subtitle}</span>
              </div>
            </div>
            <span className="rounded-full bg-[rgba(20,83,45,0.10)] px-2.5 py-1 text-[12px] font-semibold text-[#14532d]">
              {formatUnit(headgate.unit, lang)}
            </span>
          </button>

          {/* ── Measurement section ─────────────────────────── */}
          <SectionHeader>{t.log.measurement}</SectionHeader>
          <div className="mb-2 overflow-hidden rounded-[14px] bg-white p-5 shadow-[0_1px_2px_rgba(0,0,0,0.04),0_1px_0_rgba(0,0,0,0.02)]">
            <div className="flex items-baseline gap-2">
              <input
                ref={measurementRef}
                type="number"
                // Integer-count units (holes) bring up the numeric
                // keypad without a decimal key, making it physically
                // harder to type 2.5.
                inputMode={integerUnit ? "numeric" : "decimal"}
                step={integerUnit ? "1" : "any"}
                min={0}
                value={measurement}
                onChange={(e) => {
                  setMeasurement(e.target.value);
                  if (error) setError(null);
                }}
                placeholder="0"
                aria-label={t.log.measurement}
                className="min-w-0 flex-1 appearance-none bg-transparent text-[44px] font-bold leading-[1.05] tracking-tight text-[#1d1d1f] outline-none placeholder:text-[rgba(60,60,67,0.25)]"
                style={{
                  fontFamily:
                    "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
                  // Hide the native spinner buttons — they crowd a
                  // small mobile screen and feel non-native.
                  MozAppearance: "textfield",
                }}
              />
              <span className="shrink-0 pb-2 text-[20px] font-semibold text-[rgba(60,60,67,0.5)]">
                {unitLabel}
              </span>
            </div>
            {thresholdHint && (
              <p className="mt-3 border-t border-[rgba(60,60,67,0.10)] pt-3 text-[13px] text-[rgba(60,60,67,0.6)]">
                {thresholdHint}
              </p>
            )}
          </div>

          {/* Unit segmented control — labels use the localized
            *  display string so "holes" becomes "hoyos" in Spanish,
            *  while the value (the canonical DB code) stays English. */}
          <div className="mb-5">
            <SegmentedControl
              ariaLabel={t.log.unit}
              value={unit as MobileUnit}
              onChange={(v: string) => setUnit(v)}
              options={units.map((u) => ({
                value: u as string,
                label: formatUnit(u as string, lang),
              }))}
            />
          </div>

          {/* ── Timestamp section ───────────────────────────── */}
          <SectionHeader>{t.log.timestamp}</SectionHeader>
          <div className="mb-5 flex items-center gap-3 rounded-[14px] bg-white p-4 shadow-[0_1px_2px_rgba(0,0,0,0.04),0_1px_0_rgba(0,0,0,0.02)]">
            <div className="flex h-9 w-9 items-center justify-center rounded-full bg-[rgba(20,83,45,0.10)] text-[#14532d]">
              <Clock size={18} />
            </div>
            <div className="min-w-0 flex-1">
              <div className="text-[15px] font-semibold text-[#1d1d1f]">
                {t.log.loggedNow}
              </div>
              <div className="mt-0.5 truncate text-[13px] text-[rgba(60,60,67,0.6)]">
                {formatLongTimestamp(now, lang)}
              </div>
            </div>
          </div>

          {/* ── Notes section ────────────────────────────────── */}
          <SectionHeader>
            {t.log.notes}{" "}
            <span className="font-normal text-[rgba(60,60,67,0.45)]">
              — {t.log.notesOptional}
            </span>
          </SectionHeader>
          <div className="mb-5 rounded-[14px] bg-white shadow-[0_1px_2px_rgba(0,0,0,0.04),0_1px_0_rgba(0,0,0,0.02)]">
            <label className="flex items-start gap-3 p-4">
              <Pencil
                size={18}
                className="mt-0.5 shrink-0 text-[rgba(60,60,67,0.45)]"
              />
              <textarea
                value={notes}
                onChange={(e) => setNotes(e.target.value.slice(0, NOTES_MAX))}
                rows={3}
                maxLength={NOTES_MAX}
                placeholder={t.log.notesPlaceholder}
                aria-label={t.log.notes}
                className="min-h-[68px] w-full resize-none bg-transparent text-[16px] leading-[1.4] text-[#1d1d1f] outline-none placeholder:text-[rgba(60,60,67,0.4)]"
                style={{
                  fontFamily:
                    "-apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif",
                }}
              />
            </label>
            <div className="flex items-center justify-between border-t border-[rgba(60,60,67,0.10)] px-4 py-2 text-[12px] text-[rgba(60,60,67,0.45)]">
              <span>{t.log.notesVisibility}</span>
              <span>
                {notes.length}/{NOTES_MAX}
              </span>
            </div>
          </div>

          {/* Inline error */}
          {error && (
            <div
              role="alert"
              className="mb-3 rounded-[12px] bg-[rgba(255,59,48,0.10)] px-4 py-3 text-[15px] text-[#7f1d1d]"
            >
              {error}
            </div>
          )}
        </div>

        {/* ── Sticky submit bar ───────────────────────────────── */}
        <div
          className="sticky bottom-0 z-20 border-t border-[rgba(60,60,67,0.10)] bg-[rgba(255,255,255,0.92)] px-4 py-3"
          style={{
            paddingBottom: "max(env(safe-area-inset-bottom), 0.75rem)",
            backdropFilter: "blur(20px) saturate(180%)",
            WebkitBackdropFilter: "blur(20px) saturate(180%)",
          }}
        >
          <button
            type="submit"
            disabled={!canSubmit}
            className={[
              "flex h-[58px] w-full items-center justify-center gap-2 rounded-[14px] text-[17px] font-semibold",
              "transition-[transform,background-color,opacity] duration-200",
              "active:scale-[0.985]",
              canSubmit
                ? "bg-[#34C759] text-white shadow-[0_6px_18px_rgba(52,199,89,0.32),inset_0_1px_0_rgba(255,255,255,0.18)]"
                : "bg-[rgba(120,120,128,0.16)] text-[rgba(60,60,67,0.4)]",
            ].join(" ")}
          >
            {submitting ? (
              <>
                <Spinner
                  size={20}
                  className="text-white"
                  style={{ animation: "spin 0.8s linear infinite" }}
                />
                {t.log.submitting}
              </>
            ) : (
              <>
                {t.log.submit}
                {measurement && Number.isFinite(parseFloat(measurement)) && (
                  <span className="ml-1 opacity-80">
                    · {formatMeasurement(parseFloat(measurement), integerUnit)}{" "}
                    {unitLabel}
                  </span>
                )}
              </>
            )}
          </button>
        </div>
      </form>
    </div>
  );
}

// ── Section header (HIG inset-grouped style) ───────────────────────────

function SectionHeader({ children }: { children: React.ReactNode }) {
  return (
    <h2 className="mb-1.5 px-3 text-[13px] font-semibold uppercase tracking-[0.06em] text-[rgba(60,60,67,0.55)]">
      {children}
    </h2>
  );
}

/**
 * Two-letter initials for the avatar chip in the nav bar. "Tyler
 * Smith" → "TS", "Maria" → "MA". Falls back to "?" when there's no
 * usable name.
 */
function initials(name: string): string {
  const parts = name.trim().split(/\s+/).filter(Boolean);
  if (parts.length === 0) return "?";
  if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
  return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
}

export default MobileWaterLogForm;