// FieldAnalysis PWA — production build
// States: INIT → RUNNING → READY  (or REJECTED terminal)
// Real API call replaces the design-preview mock progression.

const { useState, useEffect, useRef } = React;

// ─────────────────────────────────────────────────────────────────────────────
// Klearpath logo (uses bundled PNG; falls back to wordmark if missing)
// ─────────────────────────────────────────────────────────────────────────────
function Logo({ height = 28, dark = false }) {
  const [err, setErr] = useState(false);
  if (err) {
    return (
      <span style={{
        fontFamily: FA_FONT,
        fontWeight: 700,
        fontSize: height * 0.6,
        letterSpacing: '0.04em',
        color: 'currentColor',
      }}>KLEARPATH</span>
    );
  }
  return (
    <img
      src="/static/assets/klearpath-logo.png"
      alt="Klearpath Solutions"
      onError={() => setErr(true)}
      style={{
        height, width: 'auto', display: 'block',
        filter: dark ? 'brightness(0) invert(1)' : 'none',
      }}
    />
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Inline SVG icons (no external deps — PWA must work offline)
// ─────────────────────────────────────────────────────────────────────────────
const Icon = {
  spinner: (size = 28) => (
    <svg width={size} height={size} viewBox="0 0 50 50" style={{ animation: 'fa-spin 0.9s linear infinite' }}>
      <circle cx="25" cy="25" r="20" fill="none" stroke="currentColor" strokeOpacity="0.18" strokeWidth="4"/>
      <path d="M25 5 a20 20 0 0 1 20 20" fill="none" stroke="currentColor" strokeWidth="4" strokeLinecap="round"/>
    </svg>
  ),
  shield: (size = 32) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
      <path d="M9 12l2 2 4-4"/>
    </svg>
  ),
  alert: (size = 40) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="12" cy="12" r="10"/>
      <line x1="12" y1="8" x2="12" y2="13"/>
      <line x1="12" y1="16.5" x2="12" y2="16.6"/>
    </svg>
  ),
  download: (size = 22) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
      <polyline points="7 10 12 15 17 10"/>
      <line x1="12" y1="15" x2="12" y2="3"/>
    </svg>
  ),
  chart: (size = 22) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 3v18h18"/>
      <path d="M7 16c2-3 4-7 6-7s3 5 6 5"/>
    </svg>
  ),
  residuals: (size = 22) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 3v18h18"/>
      <line x1="6" y1="12" x2="20" y2="12"/>
      <line x1="8" y1="12" x2="8" y2="9"/>
      <line x1="11" y1="12" x2="11" y2="15"/>
      <line x1="14" y1="12" x2="14" y2="8.5"/>
      <line x1="17" y1="12" x2="17" y2="14"/>
    </svg>
  ),
  back: (size = 22) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 18l-6-6 6-6"/>
      <path d="M3 12h18"/>
    </svg>
  ),
  check: (size = 64) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="12" cy="12" r="10"/>
      <polyline points="8 12.5 11 15.5 16.5 9.5"/>
    </svg>
  ),
};

// ─────────────────────────────────────────────────────────────────────────────
// Shared chrome
// ─────────────────────────────────────────────────────────────────────────────
function AppHeader({ T }) {
  return (
    <header style={{
      flex: '0 0 auto',
      padding: '18px 20px 14px',
      background: T.primary,
      color: T.primaryInk,
      borderBottom: T.name === 'Sunlight' ? `2px solid ${T.borderStrong}` : 'none',
      display: 'flex', alignItems: 'center', gap: 14,
    }}>
      <div style={{ flex: '0 0 auto', height: 30, display: 'flex', alignItems: 'center' }}>
        <Logo height={26} dark={T.name !== 'Sunlight'} />
      </div>
      <div style={{
        width: 1, height: 22, background: T.primaryInk, opacity: 0.35,
      }}/>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 15, fontWeight: 600, letterSpacing: '0.01em' }}>
          Field Analysis
        </div>
      </div>
    </header>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// State: INIT — "Awaiting valid request…"
// ─────────────────────────────────────────────────────────────────────────────
function StateInit({ T }) {
  return (
    <>
      <AppHeader T={T} />
      <main style={mainCol(T)}>
        <div style={{ color: T.textMuted, marginBottom: 24 }}>
          {Icon.spinner(48)}
        </div>
        <h1 style={h1(T)}>Awaiting valid request…</h1>
        <p style={p(T)}>
          Request analysis via Form Action → Analyze Data.
        </p>
      </main>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// State: RUNNING — "Computing analysis…"  (≥1.5s minimum)
// ─────────────────────────────────────────────────────────────────────────────
function StateRunning({ T }) {
  return (
    <>
      <AppHeader T={T} />
      <main style={mainCol(T)}>
        <div style={{ color: T.accent, marginBottom: 24 }}>
          {Icon.spinner(56)}
        </div>
        <h1 style={h1(T)}>Computing analysis…</h1>
        <p style={p(T)}>
          Fitting the compaction curve and computing residuals from your test data.
        </p>
        <ul style={{
          listStyle: 'none', padding: 0, margin: '24px 0 0',
          display: 'flex', flexDirection: 'column', gap: 8,
          fontSize: 14, color: T.textMuted, fontVariantNumeric: 'tabular-nums',
        }}>
          <li style={runRow(T, true)}>✓  Reference method loaded</li>
          <li style={runRow(T, true)}>✓  Test points validated</li>
          <li style={runRow(T, false)}>
            <span style={{ display: 'inline-flex', width: 12, marginRight: 8 }}/>
            Fitting curve · generating charts
          </li>
        </ul>
      </main>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// State: REJECTED — terminal, generic, no diagnostic info, no retry
// ─────────────────────────────────────────────────────────────────────────────
function StateRejected({ T }) {
  return (
    <>
      <AppHeader T={T} />
      <main style={{ ...mainCol(T), gap: 0 }}>
        <div style={{ color: T.danger, marginBottom: 22 }}>
          {Icon.alert(56)}
        </div>
        <h1 style={h1(T)}>This link is invalid or expired.</h1>
        <p style={p(T)}>
          You can close this page and return to your form.
        </p>
      </main>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// State: READY — thumbnails + 3 buttons + footer
// curveSrc / residSrc are data: URLs from the API response.
// ─────────────────────────────────────────────────────────────────────────────
function StateReady({ T, payload, simulateShare, curveSrc, residSrc, savedCurve, savedResid, onSaveCurve, onSaveResid }) {
  const curveImg = curveSrc || 'assets/curve.png';
  const residImg = residSrc || 'assets/residuals.png';
  const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
  const [returning, setReturning] = useState(false);
  const [toast, setToast] = useState(null);

  const showToast = (msg) => {
    setToast(msg);
    setTimeout(() => setToast(null), 2200);
  };

  const handleShare = async (kind, srcPath, filename, onDone) => {
    // On mobile: use Web Share API so the image lands in Photos.
    // On desktop: skip the share sheet and trigger a direct file download.
    try {
      if (simulateShare) {
        await new Promise(r => setTimeout(r, 500));
        onDone();
        showToast(isMobile ? `${kind} saved to Photos` : `${kind} downloaded`);
        return;
      }
      const res = await fetch(srcPath);
      const blob = await res.blob();
      if (isMobile) {
        const file = new File([blob], filename, { type: 'image/png' });
        if (navigator.canShare && navigator.canShare({ files: [file] })) {
          await navigator.share({ files: [file], title: kind });
          onDone();
          showToast(`${kind} saved to Photos`);
          return;
        }
      }
      // Desktop (or mobile without share API): direct download
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url; a.download = filename;
      document.body.appendChild(a); a.click(); a.remove();
      URL.revokeObjectURL(url);
      onDone();
      showToast(`${kind} downloaded`);
    } catch (e) {
      // Share dismissed by user — silently no-op
    }
  };

  const handleReturn = () => {
    setReturning(true);
    setTimeout(() => {
      // On iOS/Android, use the mobile deep link to open the GoFormz app.
      // On desktop/other, use the standard web URL as-is.
      const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
      const url = isMobile
        ? payload.returnUrl.replace(
            'https://app.goformz.com/forms/',
            'https://mobilelink.goformz.com/open/goformz/form/'
          )
        : payload.returnUrl;
      window.location = url;
    }, 250);
  };

  return (
    <>
      <AppHeader T={T} />

      <main style={{
        flex: 1, minHeight: 0, overflowY: 'auto',
        padding: '20px 20px 8px',
        display: 'flex', flexDirection: 'column', gap: 16,
      }}>
        <div>
          <div style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            background: T.name === 'dark' ? T.surfaceAlt : '#E6F0E0',
            color: T.success,
            padding: '5px 10px',
            borderRadius: 999,
            fontSize: 12, fontWeight: 600,
            border: T.name === 'Sunlight' ? `2px solid ${T.success}` : 'none',
          }}>
            <span style={{
              width: 7, height: 7, borderRadius: '50%', background: T.success,
            }}/>
            Analysis complete
          </div>
          <h1 style={{ ...h1(T), margin: '12px 0 4px', textAlign: 'left', fontSize: 22 }}>
            Save Charts and Analysis Results
          </h1>
          <p style={{ ...p(T), margin: 0, textAlign: 'left', fontSize: 14 }}>
            {isMobile
              ? 'Save both images to your Photos. Then upload them to your form.'
              : 'Download both images. Then upload them to your form.'}
          </p>
        </div>

        <Thumbnail
          T={T}
          src={curveImg}
          label="Proctor Curve · Field Point Overlay"
          sub="overlay.png · 800 × 600"
          icon={Icon.chart()}
          saved={savedCurve}
        />
        <Thumbnail
          T={T}
          src={residImg}
          label="Residuals · Fit Diagnostics"
          sub="residuals.png · 800 × 600"
          icon={Icon.residuals()}
          saved={savedResid}
        />

        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 4 }}>
          <BigButton
            T={T}
            tone="secondary"
            done={savedCurve}
            onClick={() => handleShare('Overlay', curveImg, 'ProctorCurveFieldPointOverlayImage.png', onSaveCurve)}
          >
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>
              {savedCurve ? Icon.check(20) : Icon.download(20)}
              {savedCurve
                ? (isMobile ? 'Overlay saved to Photos' : 'Overlay downloaded')
                : (isMobile ? 'Save Proctor Curve - Field Point Overlay to Photos' : 'Download Proctor Curve - Field Point Overlay')}
            </span>
          </BigButton>

          <BigButton
            T={T}
            tone="secondary"
            done={savedResid}
            onClick={() => handleShare('Residuals', residImg, 'ProctorResidualsImage.png', onSaveResid)}
          >
            <span style={{ display: 'inline-flex', alignItems: 'center', gap: 10 }}>
              {savedResid ? Icon.check(20) : Icon.download(20)}
              {savedResid
                ? (isMobile ? 'Residuals saved to Photos' : 'Residuals downloaded')
                : (isMobile ? 'Save Proctor Curve - Residuals to Photos' : 'Download Proctor Curve - Residuals')}
            </span>
          </BigButton>

          <BigButton
            T={T}
            tone="primary"
            disabled={returning}
            onClick={handleReturn}
          >
            {returning ? 'Returning…' : 'Send Analysis to Form'}
          </BigButton>
        </div>
      </main>

      <Footer T={T} payload={payload} />

      {toast && (
        <div style={{
          position: 'absolute', left: '50%', bottom: 96,
          transform: 'translateX(-50%)',
          background: T.text, color: T.bg,
          padding: '10px 16px', borderRadius: 999,
          fontSize: 13, fontWeight: 600,
          boxShadow: '0 6px 20px rgba(0,0,0,0.25)',
          maxWidth: '85%',
        }}>{toast}</div>
      )}
    </>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Pieces
// ─────────────────────────────────────────────────────────────────────────────
function Thumbnail({ T, src, label, sub, icon, saved }) {
  return (
    <figure style={{
      margin: 0,
      background: T.surface,
      border: `1px solid ${T.border}`,
      borderRadius: 14,
      overflow: 'hidden',
      boxShadow: T.shadow,
    }}>
      <div style={{
        position: 'relative',
        background: T.surfaceAlt,
        aspectRatio: '4 / 3',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
      }}>
        <img src={src} alt={label} style={{
          width: '100%', height: '100%', objectFit: 'contain', display: 'block',
        }}/>
        {saved && (
          <div style={{
            position: 'absolute', top: 10, right: 10,
            background: T.success, color: '#fff',
            width: 30, height: 30, borderRadius: '50%',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            boxShadow: '0 2px 8px rgba(0,0,0,0.25)',
          }}>
            {Icon.check(18)}
          </div>
        )}
      </div>
      <figcaption style={{
        padding: '10px 14px',
        display: 'flex', alignItems: 'center', gap: 10,
        borderTop: `1px solid ${T.border}`,
      }}>
        <span style={{ color: T.primary, display: 'inline-flex' }}>{icon}</span>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 14, fontWeight: 600, color: T.text }}>{label}</div>
          <div style={{ fontSize: 11, color: T.textSubtle, fontFamily: FA_FONT_MONO }}>{sub}</div>
        </div>
      </figcaption>
    </figure>
  );
}

function BigButton({ T, tone, onClick, children, disabled, done }) {
  const isPrimary = tone === 'primary';
  const bg = isPrimary
    ? (done ? T.success : T.accent)
    : (done ? (T.name === 'dark' ? T.surfaceAlt : '#E6F0E0') : T.surface);
  const ink = isPrimary ? T.accentInk : (done ? T.success : T.text);
  const border = isPrimary
    ? (done ? T.success : T.accent)
    : (done ? T.success : T.borderStrong);
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        appearance: 'none',
        minHeight: 56,
        padding: '0 18px',
        background: bg,
        color: ink,
        border: `2px solid ${border}`,
        borderRadius: 12,
        fontSize: 16,
        fontWeight: 700,
        letterSpacing: '0.01em',
        cursor: disabled ? 'not-allowed' : 'pointer',
        opacity: disabled ? 0.6 : 1,
        boxShadow: isPrimary && !done ? T.shadow : 'none',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        WebkitTapHighlightColor: 'transparent',
      }}
    >
      {children}
    </button>
  );
}

function Footer({ T, payload }) {
  return (
    <footer style={{
      flex: '0 0 auto',
      padding: '12px 20px 14px',
      background: T.surface,
      borderTop: `1px solid ${T.border}`,
      fontSize: 11,
      color: T.textSubtle,
      fontFamily: FA_FONT_MONO,
      letterSpacing: '0.01em',
      lineHeight: 1.55,
      wordBreak: 'break-all',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10 }}>
        <span>ID</span>
        <span style={{ color: T.textMuted, fontWeight: 600 }}>{payload.analysisId}</span>
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10 }}>
        <span>Method</span>
        <span style={{ color: T.textMuted }}>v{payload.methodVersion}</span>
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10 }}>
        <span>Source</span>
        <span style={{ color: T.textMuted, textAlign: 'right' }}>{payload.sourceForm}</span>
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', gap: 10 }}>
        <span>UTC</span>
        <span style={{ color: T.textMuted }}>{payload.timestamp}</span>
      </div>
    </footer>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// Style helpers
// ─────────────────────────────────────────────────────────────────────────────
const mainCol = (T) => ({
  flex: 1, minHeight: 0,
  display: 'flex', flexDirection: 'column',
  alignItems: 'center', justifyContent: 'center',
  padding: '32px 28px', textAlign: 'center', gap: 4,
  color: T.text,
});
const h1 = (T) => ({
  margin: 0, fontSize: 22, fontWeight: 700, letterSpacing: '-0.01em',
  color: T.text, lineHeight: 1.2,
});
const p = (T) => ({
  margin: '8px 0 0', fontSize: 15, lineHeight: 1.5, color: T.textMuted,
  maxWidth: 360,
});
const runRow = (T, done) => ({
  display: 'flex', alignItems: 'center', gap: 4,
  color: done ? T.success : T.textMuted,
});

// ─────────────────────────────────────────────────────────────────────────────
// Root — production entry point
// Reads query params → POST /api/analyze → drives state machine → renders UI
// ─────────────────────────────────────────────────────────────────────────────
function Root() {
  const [state, setState] = useState('INIT');
  const [apiData, setApiData] = useState(null);
  const [savedCurve, setSavedCurve] = useState(false);
  const [savedResid, setSavedResid] = useState(false);
  const T = FA_SCHEMES.light;

  useEffect(() => {
    const params = Object.fromEntries(new URLSearchParams(window.location.search));
    const MIN_RUNNING_MS = 1500;
    const startMs = Date.now();

    // Switch to RUNNING immediately so the user sees deliberate activity
    setState('RUNNING');

    fetch('/api/analyze', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(params),
    })
      .then(r => {
        if (!r.ok) throw new Error('rejected');
        return r.json();
      })
      .then(data => {
        if (!data.ok) throw new Error('rejected');
        const elapsed = Date.now() - startMs;
        const remaining = Math.max(0, MIN_RUNNING_MS - elapsed);
        setApiData(data);
        setTimeout(() => setState('READY'), remaining);
      })
      .catch(() => setState('REJECTED'));
  }, []);

  const payload = apiData ? {
    analysisId: apiData.result.analysisId,
    methodVersion: apiData.result.analysisMethodVersionReturned,
    sourceForm: `Form ID: ${apiData.result.formId}`,
    timestamp: apiData.result.timestamp,
    returnUrl: apiData.returnUrl,
  } : null;

  const curveSrc = apiData ? `data:image/png;base64,${apiData.overlayPngBase64}` : null;
  const residSrc = apiData ? `data:image/png;base64,${apiData.residualsPngBase64}` : null;

  return (
    <div style={{
      width: '100%', height: '100vh',
      background: T.bg, color: T.text,
      fontFamily: FA_FONT,
      display: 'flex', flexDirection: 'column',
      overflow: 'hidden',
    }}>
      {state === 'INIT'     && <StateInit T={T} />}
      {state === 'REJECTED' && <StateRejected T={T} />}
      {state === 'RUNNING'  && <StateRunning T={T} />}
      {state === 'READY' && payload && (
        <StateReady
          T={T}
          payload={payload}
          simulateShare={false}
          curveSrc={curveSrc}
          residSrc={residSrc}
          savedCurve={savedCurve}
          savedResid={savedResid}
          onSaveCurve={() => setSavedCurve(true)}
          onSaveResid={() => setSavedResid(true)}
        />
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<Root />);
