// JWT Codec — decode and inspect JWT tokens (header, payload, signature).

window.TOOL_HANDLERS['jwt-codec'] = function JwtCodecTool() {
  const [token, setToken] = React.useState('');
  const [copied, setCopied] = React.useState('');

  // Base64url decode helper
  var b64urlDecode = function (str) {
    var padded = str.replace(/-/g, '+').replace(/_/g, '/');
    while (padded.length % 4 !== 0) padded += '=';
    return atob(padded);
  };

  var parsed = React.useMemo(function () {
    if (!token.trim()) return null;

    var parts = token.trim().split('.');
    if (parts.length !== 3) return { error: 'A valid JWT has exactly 3 parts separated by dots (header.payload.signature).' };

    try {
      var headerJson = b64urlDecode(parts[0]);
      var header = JSON.parse(headerJson);
    } catch (e) {
      return { error: 'Failed to decode JWT header — not valid Base64url JSON.' };
    }

    try {
      var payloadJson = b64urlDecode(parts[1]);
      var payload = JSON.parse(payloadJson);
    } catch (e) {
      return { error: 'Failed to decode JWT payload — not valid Base64url JSON.' };
    }

    var signature = parts[2];

    // Check expiry
    var isExpired = false;
    var now = Math.floor(Date.now() / 1000);
    if (payload.exp && typeof payload.exp === 'number') {
      isExpired = payload.exp < now;
    }

    return { header: header, payload: payload, signature: signature, isExpired: isExpired };
  }, [token]);

  var formatDate = function (ts) {
    if (!ts || typeof ts !== 'number') return null;
    try {
      return new Date(ts * 1000).toLocaleString();
    } catch (e) {
      return null;
    }
  };

  var copy = function (text, label) {
    navigator.clipboard.writeText(text);
    setCopied(label);
    setTimeout(function () { setCopied(''); }, 1500);
  };

  var sectionStyle = function (bg) {
    return {
      padding: '12px 14px', borderRadius: 10, marginBottom: 10,
      background: bg, border: '1px solid var(--id-border)',
      position: 'relative', overflow: 'hidden'
    };
  };

  var labelStyle = {
    fontWeight: 700, fontSize: 11, textTransform: 'uppercase', letterSpacing: '0.5px',
    marginBottom: 6, display: 'flex', alignItems: 'center', justifyContent: 'space-between'
  };

  var codeStyle = {
    fontFamily: 'monospace', fontSize: 12, whiteSpace: 'pre-wrap', wordBreak: 'break-all',
    color: 'var(--id-text)', lineHeight: 1.5
  };

  // Render claim dates inline
  var renderPayloadWithDates = function (payload) {
    var json = JSON.stringify(payload, null, 2);
    var dateFields = ['exp', 'iat', 'nbf', 'auth_time'];
    var notes = [];
    dateFields.forEach(function (field) {
      if (payload[field] && typeof payload[field] === 'number') {
        var human = formatDate(payload[field]);
        if (human) notes.push(field + ': ' + human);
      }
    });
    return { json: json, notes: notes };
  };

  return (
    <div className="mini-tool">
      <div className="mini-label">Paste JWT Token</div>
      <textarea
        className="mini-input mini-textarea"
        style={{ minHeight: 100, fontFamily: 'monospace', fontSize: 12 }}
        placeholder="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U"
        value={token}
        onChange={function (e) { setToken(e.target.value); }}
      />

      {parsed && parsed.error && (
        <div style={{
          marginTop: 12, padding: '10px 14px', borderRadius: 8,
          background: 'rgba(200,50,30,0.1)', color: '#c8321f',
          fontSize: 13, fontWeight: 500
        }}>
          <window.Icon name="x" size={14} /> {parsed.error}
        </div>
      )}

      {parsed && !parsed.error && (
        <div style={{ marginTop: 16 }}>
          {/* Expired badge */}
          {parsed.isExpired && (
            <div style={{
              display: 'inline-flex', alignItems: 'center', gap: 6,
              padding: '4px 12px', borderRadius: 20, marginBottom: 12,
              background: 'rgba(200,50,30,0.12)', color: '#c8321f',
              fontSize: 12, fontWeight: 700
            }}>
              <window.Icon name="x" size={12} /> Token is expired
            </div>
          )}

          {/* Header */}
          <div style={sectionStyle('rgba(220,80,60,0.06)')}>
            <div style={labelStyle}>
              <span style={{ color: '#c8321f' }}>Header</span>
              <button
                className="icon-btn"
                onClick={function () { copy(JSON.stringify(parsed.header, null, 2), 'header'); }}
                aria-label="Copy header"
                style={copied === 'header' ? { color: 'var(--id-success)' } : {}}
              >
                <window.Icon name={copied === 'header' ? 'check' : 'doc'} size={13} />
              </button>
            </div>
            <pre style={codeStyle}>{JSON.stringify(parsed.header, null, 2)}</pre>
          </div>

          {/* Payload */}
          {(function () {
            var info = renderPayloadWithDates(parsed.payload);
            return (
              <div style={sectionStyle('rgba(50,100,220,0.06)')}>
                <div style={labelStyle}>
                  <span style={{ color: '#2563eb' }}>Payload</span>
                  <button
                    className="icon-btn"
                    onClick={function () { copy(info.json, 'payload'); }}
                    aria-label="Copy payload"
                    style={copied === 'payload' ? { color: 'var(--id-success)' } : {}}
                  >
                    <window.Icon name={copied === 'payload' ? 'check' : 'doc'} size={13} />
                  </button>
                </div>
                <pre style={codeStyle}>{info.json}</pre>
                {info.notes.length > 0 && (
                  <div style={{ marginTop: 8, fontSize: 11, color: 'var(--id-text-muted)', lineHeight: 1.6 }}>
                    {info.notes.map(function (n, i) {
                      return React.createElement('div', { key: i }, React.createElement(window.Icon, { name: 'clock', size: 11 }), ' ', n);
                    })}
                  </div>
                )}
              </div>
            );
          })()}

          {/* Signature */}
          <div style={sectionStyle('rgba(16,128,90,0.06)')}>
            <div style={labelStyle}>
              <span style={{ color: '#10805a' }}>Signature</span>
              <button
                className="icon-btn"
                onClick={function () { copy(parsed.signature, 'sig'); }}
                aria-label="Copy signature"
                style={copied === 'sig' ? { color: 'var(--id-success)' } : {}}
              >
                <window.Icon name={copied === 'sig' ? 'check' : 'doc'} size={13} />
              </button>
            </div>
            <code style={Object.assign({}, codeStyle, { fontSize: 11 })}>{parsed.signature}</code>
          </div>
        </div>
      )}
    </div>
  );
};
