// Profile detail page: view mode + visually-distinct edit mode + avatar crop modal.

function ProfileView({ user, onLogout, onUserUpdated, setView }) {
  const [mode, setMode] = React.useState('view');
  const [draftName, setDraftName] = React.useState(user.display_name || '');
  const [draftAvatar, setDraftAvatar] = React.useState(user.avatar_url || null);
  const [saving, setSaving] = React.useState(false);
  const [errorMsg, setErrorMsg] = React.useState(null);
  const [cropFile, setCropFile] = React.useState(null);
  const fileInputRef = React.useRef(null);

  const enterEdit = () => {
    setDraftName(user.display_name || '');
    setDraftAvatar(user.avatar_url || null);
    setErrorMsg(null);
    setMode('edit');
  };

  const cancelEdit = () => {
    setErrorMsg(null);
    setMode('view');
  };

  const save = async () => {
    const name = draftName.trim();
    if (!name) { setErrorMsg('Display name cannot be empty.'); return; }
    if (name.length > 40) { setErrorMsg('Display name is too long (max 40 chars).'); return; }

    const patch = {};
    if (name !== (user.display_name || '')) patch.display_name = name;
    if (draftAvatar !== (user.avatar_url || null)) patch.avatar_url = draftAvatar;

    if (Object.keys(patch).length === 0) { setMode('view'); return; }

    setSaving(true);
    setErrorMsg(null);
    try {
      const d = await window.SnatchAPI.updateProfile(patch);
      onUserUpdated && onUserUpdated(d.user);
      setMode('view');
    } catch (err) {
      setErrorMsg(err.message || 'Save failed.');
    } finally {
      setSaving(false);
    }
  };

  const handleFilePick = (e) => {
    const f = e.target.files && e.target.files[0];
    e.target.value = '';
    if (!f) return;
    if (!f.type.startsWith('image/')) { setErrorMsg('Please pick an image file.'); return; }
    if (f.size > 10 * 1024 * 1024) { setErrorMsg('Image is too large (max 10 MB raw).'); return; }
    setErrorMsg(null);
    setCropFile(f);
  };

  const displayName = user.display_name || 'Athlete';
  const avatarUrl = mode === 'edit' ? draftAvatar : user.avatar_url;
  const initial = (user.display_name || user.email || '?').slice(0, 1).toUpperCase();

  return (
    <div style={{ minHeight: 'calc(100vh - 82px)', padding: '56px 24px 80px', display: 'flex', justifyContent: 'center' }}>
      <div style={{ width: '100%', maxWidth: 560 }}>
        {mode === 'view' ? (
          <ProfileViewMode
            displayName={displayName}
            email={user.email}
            avatarUrl={avatarUrl}
            initial={initial}
            onEdit={enterEdit}
            onLogout={onLogout}
          />
        ) : (
          <ProfileEditMode
            draftName={draftName}
            setDraftName={setDraftName}
            draftAvatar={draftAvatar}
            setDraftAvatar={setDraftAvatar}
            email={user.email}
            initial={initial}
            saving={saving}
            errorMsg={errorMsg}
            onCancel={cancelEdit}
            onSave={save}
            onPickFile={() => fileInputRef.current && fileInputRef.current.click()}
          />
        )}

        <input
          ref={fileInputRef}
          type="file"
          accept="image/png,image/jpeg,image/webp"
          onChange={handleFilePick}
          style={{ display: 'none' }}
        />
      </div>

      {cropFile && (
        <AvatarCropModal
          file={cropFile}
          onCancel={() => setCropFile(null)}
          onConfirm={(dataUrl) => { setDraftAvatar(dataUrl); setCropFile(null); }}
        />
      )}
    </div>
  );
}

function Avatar({ url, initial, size }) {
  const style = {
    width: size, height: size, borderRadius: '50%',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    color: '#fff', fontFamily: 'Barlow Condensed', fontWeight: 900,
    fontSize: size * 0.42, letterSpacing: '0.02em',
    flexShrink: 0,
  };
  if (url) {
    return <div style={{ ...style, background: `#1a1a1a url(${url}) center/cover`, border: '3px solid rgba(255,255,255,0.1)' }} />;
  }
  return (
    <div style={{ ...style, background: 'linear-gradient(135deg, var(--accent), #ff8a3d)', border: '3px solid rgba(255,255,255,0.15)' }}>
      {initial}
    </div>
  );
}

function ProfileViewMode({ displayName, email, avatarUrl, initial, onEdit, onLogout }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', gap: 0 }}>
      <div className="mono" style={{ fontSize: 11, letterSpacing: '0.3em', color: 'var(--accent)', marginBottom: 24 }}>● YOUR PROFILE</div>

      <Avatar url={avatarUrl} initial={initial} size={160} />

      <div className="display" style={{ fontSize: 'clamp(40px, 6vw, 56px)', lineHeight: 1, marginTop: 28, color: '#fff' }}>
        {displayName}
      </div>
      <div className="mono" style={{ fontSize: 13, letterSpacing: '0.12em', color: 'rgba(255,255,255,0.5)', marginTop: 14 }}>
        {email}
      </div>

      <button
        onClick={onEdit}
        className="btn btn-ghost"
        style={{
          marginTop: 40, padding: '14px 28px', fontSize: 13,
          background: 'transparent', border: '1.5px solid rgba(255,255,255,0.25)',
          color: '#fff', cursor: 'pointer', borderRadius: 2,
          fontFamily: 'Archivo', fontWeight: 800, letterSpacing: '0.12em', textTransform: 'uppercase',
        }}
      >✎ Edit profile</button>

      <div style={{ width: '100%', height: 1, background: 'rgba(255,255,255,0.08)', marginTop: 72 }} />

      <button
        onClick={onLogout}
        style={{
          marginTop: 28, padding: '14px 28px',
          background: 'transparent', border: '1.5px solid rgba(255,45,45,0.45)',
          color: '#ff8a8a', cursor: 'pointer', borderRadius: 2,
          fontFamily: 'Archivo', fontWeight: 800, fontSize: 13,
          letterSpacing: '0.12em', textTransform: 'uppercase',
        }}
      >Log out</button>
    </div>
  );
}

function ProfileEditMode({ draftName, setDraftName, draftAvatar, setDraftAvatar, email, initial, saving, errorMsg, onCancel, onSave, onPickFile }) {
  return (
    <div style={{
      position: 'relative',
      background: 'linear-gradient(180deg, rgba(255,45,45,0.06), rgba(255,255,255,0.02))',
      border: '1px solid rgba(255,45,45,0.35)',
      borderLeft: '4px solid var(--accent)',
      borderRadius: 4,
      padding: '40px 36px 32px',
      boxShadow: '0 30px 60px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.02)',
    }}>
      <div className="mono" style={{ fontSize: 11, letterSpacing: '0.3em', color: 'var(--accent)', marginBottom: 28, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <span>● EDITING PROFILE</span>
        <span style={{ opacity: 0.5, fontSize: 10 }}>CHANGES NOT SAVED</span>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
        <Avatar url={draftAvatar} initial={initial} size={120} />
        <div style={{ display: 'flex', gap: 8, marginTop: 16 }}>
          <button
            onClick={onPickFile}
            style={{
              padding: '9px 16px', background: 'rgba(255,255,255,0.08)',
              border: '1px solid rgba(255,255,255,0.2)', color: '#fff',
              fontFamily: 'Archivo', fontWeight: 700, fontSize: 11,
              letterSpacing: '0.14em', textTransform: 'uppercase',
              cursor: 'pointer', borderRadius: 2,
            }}
          >Change picture</button>
          {draftAvatar && (
            <button
              onClick={() => setDraftAvatar(null)}
              style={{
                padding: '9px 12px', background: 'transparent',
                border: 0, color: 'rgba(255,255,255,0.45)',
                fontFamily: 'Archivo', fontSize: 12,
                cursor: 'pointer', textDecoration: 'underline',
              }}
            >Remove</button>
          )}
        </div>
      </div>

      <div style={{ marginTop: 36 }}>
        <label className="mono" style={{ fontSize: 10, letterSpacing: '0.22em', color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase' }}>Display name</label>
        <input
          value={draftName}
          onChange={(e) => setDraftName(e.target.value)}
          maxLength={40}
          style={{
            display: 'block', width: '100%', marginTop: 8,
            background: 'transparent', border: 0, borderBottom: '2px solid rgba(255,255,255,0.3)',
            color: '#fff', fontFamily: 'Archivo', fontWeight: 700, fontSize: 24,
            padding: '8px 0', outline: 'none',
          }}
          onFocus={(e) => e.target.style.borderBottomColor = 'var(--accent)'}
          onBlur={(e) => e.target.style.borderBottomColor = 'rgba(255,255,255,0.3)'}
        />
        <div className="mono" style={{ fontSize: 10, letterSpacing: '0.16em', color: 'rgba(255,255,255,0.35)', marginTop: 6 }}>
          {draftName.length}/40
        </div>
      </div>

      <div style={{ marginTop: 24 }}>
        <label className="mono" style={{ fontSize: 10, letterSpacing: '0.22em', color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase' }}>Email (managed by Google)</label>
        <div style={{
          marginTop: 8, padding: '10px 0', borderBottom: '2px solid rgba(255,255,255,0.08)',
          color: 'rgba(255,255,255,0.45)', fontSize: 15,
        }}>{email}</div>
      </div>

      {errorMsg && (
        <div style={{ marginTop: 20, padding: '10px 14px', border: '1px solid rgba(255,45,45,0.4)', background: 'rgba(255,45,45,0.1)', color: '#fca', fontSize: 13, borderRadius: 3 }}>
          {errorMsg}
        </div>
      )}

      <div style={{ display: 'flex', gap: 10, marginTop: 32 }}>
        <button
          onClick={onSave}
          disabled={saving}
          className="btn btn-primary"
          style={{ flex: 1, padding: '14px 20px', fontSize: 13, opacity: saving ? 0.6 : 1 }}
        >{saving ? 'Saving...' : 'Save changes'}</button>
        <button
          onClick={onCancel}
          disabled={saving}
          style={{
            padding: '14px 20px',
            background: 'transparent', border: '1.5px solid rgba(255,255,255,0.25)',
            color: '#fff', cursor: 'pointer', borderRadius: 2,
            fontFamily: 'Archivo', fontWeight: 800, fontSize: 13,
            letterSpacing: '0.12em', textTransform: 'uppercase',
          }}
        >Cancel</button>
      </div>
    </div>
  );
}

// ===== Avatar crop modal =====
// Canvas-based drag + zoom. Confirm renders a 256x256 JPEG data URL.

function AvatarCropModal({ file, onCancel, onConfirm }) {
  const [img, setImg] = React.useState(null);        // HTMLImageElement
  const [imgError, setImgError] = React.useState(null);
  const [scale, setScale] = React.useState(1);       // relative to "fit to crop box"
  const [offset, setOffset] = React.useState({ x: 0, y: 0 }); // image center offset from crop center, in screen px
  const canvasRef = React.useRef(null);
  const previewRef = React.useRef(null);
  const dragRef = React.useRef(null);

  const CROP_DISPLAY_SIZE = 300; // on-screen crop square (the white frame in canvas)
  const OUTPUT_SIZE = 256;       // final exported avatar size

  // Load the file.
  React.useEffect(() => {
    const reader = new FileReader();
    reader.onload = () => {
      const image = new Image();
      image.onload = () => setImg(image);
      image.onerror = () => setImgError('Could not read that image.');
      image.src = reader.result;
    };
    reader.onerror = () => setImgError('Could not read that file.');
    reader.readAsDataURL(file);
  }, [file]);

  // Compute the "fit" scale so the shorter side of the image equals the crop box.
  const baseFit = React.useMemo(() => {
    if (!img) return 1;
    const minSide = Math.min(img.width, img.height);
    return CROP_DISPLAY_SIZE / minSide;
  }, [img]);

  // Clamp offset so the image always covers the crop box.
  const clampOffset = React.useCallback((ox, oy, s) => {
    if (!img) return { x: ox, y: oy };
    const displayedW = img.width * baseFit * s;
    const displayedH = img.height * baseFit * s;
    const maxX = Math.max(0, (displayedW - CROP_DISPLAY_SIZE) / 2);
    const maxY = Math.max(0, (displayedH - CROP_DISPLAY_SIZE) / 2);
    return {
      x: Math.max(-maxX, Math.min(maxX, ox)),
      y: Math.max(-maxY, Math.min(maxY, oy)),
    };
  }, [img, baseFit]);

  // Draw to canvas + live round preview.
  React.useEffect(() => {
    if (!img) return;
    const canvas = canvasRef.current;
    const preview = previewRef.current;
    if (!canvas) return;

    const dpr = window.devicePixelRatio || 1;
    const cw = CROP_DISPLAY_SIZE + 80;
    const ch = CROP_DISPLAY_SIZE + 80;
    canvas.width = cw * dpr;
    canvas.height = ch * dpr;
    canvas.style.width = cw + 'px';
    canvas.style.height = ch + 'px';
    const ctx = canvas.getContext('2d');
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    ctx.fillStyle = '#0a0a0a';
    ctx.fillRect(0, 0, cw, ch);

    const displayedW = img.width * baseFit * scale;
    const displayedH = img.height * baseFit * scale;
    const cx = cw / 2 + offset.x;
    const cy = ch / 2 + offset.y;
    ctx.drawImage(img, cx - displayedW / 2, cy - displayedH / 2, displayedW, displayedH);

    // Dim outside the crop square.
    const cropX = (cw - CROP_DISPLAY_SIZE) / 2;
    const cropY = (ch - CROP_DISPLAY_SIZE) / 2;
    ctx.fillStyle = 'rgba(10,10,10,0.7)';
    ctx.fillRect(0, 0, cw, cropY);
    ctx.fillRect(0, cropY + CROP_DISPLAY_SIZE, cw, cropY);
    ctx.fillRect(0, cropY, cropX, CROP_DISPLAY_SIZE);
    ctx.fillRect(cropX + CROP_DISPLAY_SIZE, cropY, cropX, CROP_DISPLAY_SIZE);

    // Crop frame.
    ctx.strokeStyle = '#fff';
    ctx.lineWidth = 1.5;
    ctx.strokeRect(cropX + 0.75, cropY + 0.75, CROP_DISPLAY_SIZE - 1.5, CROP_DISPLAY_SIZE - 1.5);

    // Live preview (round): re-render just the crop area.
    if (preview) {
      const psize = 120;
      preview.width = psize * dpr;
      preview.height = psize * dpr;
      preview.style.width = psize + 'px';
      preview.style.height = psize + 'px';
      const pctx = preview.getContext('2d');
      pctx.setTransform(dpr, 0, 0, dpr, 0, 0);
      pctx.clearRect(0, 0, psize, psize);
      const ratio = psize / CROP_DISPLAY_SIZE;
      const cxP = psize / 2 + offset.x * ratio;
      const cyP = psize / 2 + offset.y * ratio;
      pctx.drawImage(img, cxP - (displayedW * ratio) / 2, cyP - (displayedH * ratio) / 2, displayedW * ratio, displayedH * ratio);
    }
  }, [img, baseFit, scale, offset]);

  const onMouseDown = (e) => {
    dragRef.current = { startX: e.clientX, startY: e.clientY, ox: offset.x, oy: offset.y };
  };
  const onMouseMove = (e) => {
    if (!dragRef.current) return;
    const dx = e.clientX - dragRef.current.startX;
    const dy = e.clientY - dragRef.current.startY;
    setOffset(clampOffset(dragRef.current.ox + dx, dragRef.current.oy + dy, scale));
  };
  const onMouseUp = () => { dragRef.current = null; };

  React.useEffect(() => {
    const up = () => { dragRef.current = null; };
    window.addEventListener('mouseup', up);
    return () => window.removeEventListener('mouseup', up);
  }, []);

  const onWheel = (e) => {
    e.preventDefault();
    const delta = -e.deltaY * 0.002;
    const next = Math.max(1, Math.min(4, scale + delta));
    setScale(next);
    setOffset(o => clampOffset(o.x, o.y, next));
  };

  const changeScale = (next) => {
    const s = Math.max(1, Math.min(4, next));
    setScale(s);
    setOffset(o => clampOffset(o.x, o.y, s));
  };

  const confirm = () => {
    if (!img) return;
    const out = document.createElement('canvas');
    out.width = OUTPUT_SIZE;
    out.height = OUTPUT_SIZE;
    const ctx = out.getContext('2d');
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, OUTPUT_SIZE, OUTPUT_SIZE);

    // Map the on-screen crop box back to source image pixels.
    // displayedW corresponds to img.width on-canvas; source pixel per display px = 1 / (baseFit * scale)
    const srcPerDisplay = 1 / (baseFit * scale);
    const srcCropSize = CROP_DISPLAY_SIZE * srcPerDisplay;
    // Image center on canvas is cw/2 + offset.x. Crop center on canvas is cw/2. Difference (-offset) maps to src units.
    const srcCenterX = img.width / 2 - offset.x * srcPerDisplay;
    const srcCenterY = img.height / 2 - offset.y * srcPerDisplay;
    const srcX = srcCenterX - srcCropSize / 2;
    const srcY = srcCenterY - srcCropSize / 2;

    ctx.drawImage(img, srcX, srcY, srcCropSize, srcCropSize, 0, 0, OUTPUT_SIZE, OUTPUT_SIZE);

    // Try progressively more aggressive quality until we fit under 200 KB.
    let quality = 0.9;
    let dataUrl = out.toDataURL('image/jpeg', quality);
    while (dataUrlBytes(dataUrl) > 180 * 1024 && quality > 0.4) {
      quality -= 0.1;
      dataUrl = out.toDataURL('image/jpeg', quality);
    }
    onConfirm(dataUrl);
  };

  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 1000,
      background: 'rgba(0,0,0,0.8)', backdropFilter: 'blur(6px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 24,
    }} onMouseUp={onMouseUp}>
      <div style={{
        background: '#111', border: '1px solid #2a2a2a', borderRadius: 6,
        padding: 28, color: '#fff', width: '100%', maxWidth: 640,
        boxShadow: '0 40px 80px rgba(0,0,0,0.7)',
      }}>
        <div className="mono" style={{ fontSize: 11, letterSpacing: '0.3em', color: 'var(--accent)', marginBottom: 6 }}>● CROP AVATAR</div>
        <div className="display" style={{ fontSize: 26, marginBottom: 20 }}>Frame your picture</div>

        {imgError && (
          <div style={{ padding: 16, border: '1px solid rgba(255,45,45,0.4)', background: 'rgba(255,45,45,0.1)', color: '#fca', fontSize: 13, marginBottom: 16 }}>{imgError}</div>
        )}

        <div style={{ display: 'flex', gap: 24, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'center' }}>
          <canvas
            ref={canvasRef}
            onMouseDown={onMouseDown}
            onMouseMove={onMouseMove}
            onWheel={onWheel}
            style={{ cursor: dragRef.current ? 'grabbing' : 'grab', borderRadius: 4, touchAction: 'none' }}
          />
          <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10 }}>
            <div style={{ width: 120, height: 120, borderRadius: '50%', overflow: 'hidden', border: '3px solid rgba(255,255,255,0.15)', background: '#0a0a0a' }}>
              <canvas ref={previewRef} />
            </div>
            <div className="mono" style={{ fontSize: 10, letterSpacing: '0.2em', color: 'rgba(255,255,255,0.5)' }}>PREVIEW</div>
          </div>
        </div>

        <div style={{ marginTop: 20 }}>
          <div className="mono" style={{ fontSize: 10, letterSpacing: '0.2em', color: 'rgba(255,255,255,0.5)', marginBottom: 8 }}>ZOOM</div>
          <input
            type="range"
            min="1"
            max="4"
            step="0.01"
            value={scale}
            onChange={(e) => changeScale(parseFloat(e.target.value))}
            style={{ width: '100%' }}
          />
          <div className="mono" style={{ fontSize: 10, letterSpacing: '0.14em', color: 'rgba(255,255,255,0.4)', marginTop: 8 }}>
            DRAG TO PAN · SCROLL OR SLIDER TO ZOOM
          </div>
        </div>

        <div style={{ display: 'flex', gap: 10, marginTop: 24 }}>
          <button
            onClick={confirm}
            disabled={!img}
            className="btn btn-primary"
            style={{ flex: 1, padding: '14px 20px', fontSize: 13, opacity: img ? 1 : 0.5 }}
          >Use this picture</button>
          <button
            onClick={onCancel}
            style={{
              padding: '14px 20px',
              background: 'transparent', border: '1.5px solid rgba(255,255,255,0.25)',
              color: '#fff', cursor: 'pointer', borderRadius: 2,
              fontFamily: 'Archivo', fontWeight: 800, fontSize: 13,
              letterSpacing: '0.12em', textTransform: 'uppercase',
            }}
          >Cancel</button>
        </div>
      </div>
    </div>
  );
}

function dataUrlBytes(dataUrl) {
  const comma = dataUrl.indexOf(',');
  if (comma < 0) return dataUrl.length;
  const b64 = dataUrl.slice(comma + 1);
  const pad = b64.endsWith('==') ? 2 : b64.endsWith('=') ? 1 : 0;
  return Math.floor((b64.length * 3) / 4) - pad;
}

Object.assign(window, { ProfileView, AvatarCropModal });
