﻿/* Databricks SQL lab */

function DatabricksPage({ tweaks, onBackHome }) {
  const primary = tweaks.primaryColor;
  const [code, setCode] = React.useState('');
  const [unlocked, setUnlocked] = React.useState(false);
  const [unlockLoading, setUnlockLoading] = React.useState(false);
  const [unlockError, setUnlockError] = React.useState('');
  const [jdbcUrl, setJdbcUrl] = React.useState(DEFAULT_DATABRICKS_JDBC_URL);
  const [token, setToken] = React.useState('');
  const [statement, setStatement] = React.useState(DEFAULT_DATABRICKS_QUERY);
  const [rowLimit, setRowLimit] = React.useState(50);
  const [loading, setLoading] = React.useState(false);
  const [error, setError] = React.useState('');
  const [result, setResult] = React.useState(null);

  const parsed = React.useMemo(() => {
    try {
      return parseDatabricksJdbcUrlPreview(jdbcUrl);
    } catch (err) {
      return { error: err.message };
    }
  }, [jdbcUrl]);

  const canRun = !loading && !parsed.error && token.trim() && statement.trim();

  const unlock = async (candidateCode) => {
    const trimmedCode = candidateCode.trim();
    setUnlockLoading(true);
    setUnlockError('');
    try {
      await verifyJourneyCode(trimmedCode);
      sessionStorage.setItem(JOURNEY_CODE_STORAGE_KEY, trimmedCode);
      setCode(trimmedCode);
      setUnlocked(true);
    } catch (err) {
      sessionStorage.removeItem(JOURNEY_CODE_STORAGE_KEY);
      setUnlocked(false);
      setUnlockError(err.message === 'Invalid code' ? 'Code is not correct.' : err.message);
    } finally {
      setUnlockLoading(false);
    }
  };

  React.useEffect(() => {
    const savedCode = sessionStorage.getItem(JOURNEY_CODE_STORAGE_KEY);
    if (savedCode) unlock(savedCode);
  }, []);

  const runQuery = async (event) => {
    event.preventDefault();
    if (!canRun) return;

    setLoading(true);
    setError('');
    setResult(null);

    try {
      const response = await fetch('/api/databricks/query', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          jdbcUrl,
          token,
          statement,
          rowLimit,
          code,
        }),
      });
      const payload = await response.json().catch(() => null);

      if (!response.ok || !payload?.ok) {
        throw new Error(payload?.error || 'Databricks query failed.');
      }

      setResult(payload);
    } catch (err) {
      setError(err.message || 'Databricks query failed.');
    } finally {
      setLoading(false);
    }
  };

  if (!unlocked) {
    return (
      <main className="databricks-page" style={{
        minHeight: '100vh',
        padding: '124px 80px 80px',
        background: 'var(--theme-bg)',
        color: 'var(--theme-text)',
      }}>
        <div className="journey-lock" style={{
          maxWidth: 540,
          margin: '8vh auto 0',
          padding: 34,
          borderRadius: 20,
          background: 'rgba(var(--theme-surface-rgb),0.24)',
          border: '1px solid rgba(var(--theme-text-rgb),0.08)',
          boxShadow: '0 24px 60px rgba(0,0,0,0.24)',
        }}>
          <div style={{
            width: 54,
            height: 54,
            borderRadius: 16,
            background: `${primary}18`,
            color: primary,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            marginBottom: 22,
          }}>
            <DatabricksIcon size={26}/>
          </div>
          <div style={{
            fontSize: 12,
            fontWeight: 800,
            color: primary,
            letterSpacing: '3px',
            textTransform: 'uppercase',
            marginBottom: 10,
          }}>Private Databricks lab</div>
          <h1 style={{
            fontFamily: 'Poppins, sans-serif',
            fontWeight: 700,
            fontSize: 'clamp(34px, 5vw, 52px)',
            color: 'var(--theme-strong)',
            lineHeight: 1.05,
            margin: '0 0 14px',
          }}>Databricks SQL Lab</h1>
          <p style={{
            color: 'rgba(var(--theme-text-rgb),0.68)',
            fontSize: 15,
            lineHeight: 1.7,
            margin: '0 0 26px',
          }}>
            Uses the Journey code before opening the Databricks SQL runner.
          </p>

          <form onSubmit={(event) => {
            event.preventDefault();
            unlock(code);
          }} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <input
              value={code}
              onChange={event => setCode(event.target.value)}
              placeholder="32-character secret code"
              autoComplete="off"
              spellCheck="false"
              style={databricksFieldStyle()}
            />
            {unlockError && (
              <div style={databricksNoticeStyle('#EF4444')}>{unlockError}</div>
            )}
            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 4 }}>
              <button type="submit" disabled={unlockLoading || code.trim().length !== 32} style={{
                ...deButtonStyle(primary, true),
                opacity: unlockLoading || code.trim().length !== 32 ? 0.55 : 1,
              }}>
                {unlockLoading ? 'Checking...' : 'Unlock'}
              </button>
              <button type="button" onClick={onBackHome} style={deButtonStyle(primary, false)}>Back home</button>
            </div>
          </form>
        </div>
      </main>
    );
  }

  return (
    <main className="databricks-page" style={{
      minHeight: '100vh',
      padding: '118px clamp(20px, 4vw, 64px) 80px',
      background: 'var(--theme-bg)',
      color: 'var(--theme-text)',
      animation: 'fadeIn 0.3s ease',
    }}>
      <div style={{ width: '100%', maxWidth: 1260, margin: '0 auto' }}>
        <div className="databricks-header" style={{
          display: 'flex',
          alignItems: 'flex-start',
          justifyContent: 'space-between',
          gap: 20,
          marginBottom: 24,
        }}>
          <div style={{ maxWidth: 820 }}>
            <div style={{
              fontSize: 12,
              fontWeight: 800,
              letterSpacing: '3px',
              textTransform: 'uppercase',
              color: primary,
              marginBottom: 10,
            }}>Admin workspace</div>
            <h1 style={{
              margin: 0,
              color: 'var(--theme-strong)',
              fontSize: 'clamp(38px, 5vw, 62px)',
              lineHeight: 1.05,
            }}>Databricks SQL Lab</h1>
            <p style={{
              margin: '12px 0 0',
              color: 'rgba(var(--theme-text-rgb),0.66)',
              lineHeight: 1.7,
              fontSize: 15,
            }}>
              Practice with your Databricks JDBC details through a server proxy to the SQL Statement Execution API.
            </p>
          </div>
          <div className="databricks-actions" style={{ display: 'flex', gap: 10, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
            <button type="button" onClick={() => {
              sessionStorage.removeItem(JOURNEY_CODE_STORAGE_KEY);
              setUnlocked(false);
              setCode('');
            }} style={deButtonStyle(primary, false)}>Lock</button>
            <button type="button" onClick={onBackHome} style={deButtonStyle(primary, false)}>Back home</button>
          </div>
        </div>

        <form onSubmit={runQuery} className="databricks-grid" style={{
          display: 'grid',
          gridTemplateColumns: 'minmax(0, 0.92fr) minmax(0, 1.08fr)',
          gap: 18,
          alignItems: 'start',
        }}>
          <section className="databricks-card" style={databricksCardStyle()}>
            <div style={{
              display: 'flex',
              alignItems: 'center',
              gap: 12,
              marginBottom: 18,
            }}>
              <div style={{
                width: 46,
                height: 46,
                borderRadius: 15,
                background: `${primary}18`,
                color: primary,
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
              }}>
                <DatabricksIcon size={24}/>
              </div>
              <div>
                <h2 style={{ margin: 0, color: 'var(--theme-strong)', fontSize: 22 }}>Connection</h2>
                <div style={{ marginTop: 4, color: 'rgba(var(--theme-text-rgb),0.54)', fontSize: 13 }}>
                  JDBC URL is parsed here; token is never saved.
                </div>
              </div>
            </div>

            <label style={databricksLabelStyle()}>
              JDBC URL
              <textarea
                value={jdbcUrl}
                onChange={event => setJdbcUrl(event.target.value)}
                spellCheck="false"
                rows={5}
                style={{ ...databricksFieldStyle(), resize: 'vertical', lineHeight: 1.55 }}
              />
            </label>

            <label style={databricksLabelStyle()}>
              Databricks PAT
              <input
                type="password"
                value={token}
                onChange={event => setToken(event.target.value)}
                placeholder="Paste personal access token"
                autoComplete="off"
                spellCheck="false"
                style={databricksFieldStyle()}
              />
            </label>

            <label style={databricksLabelStyle()}>
              Row limit
              <input
                type="number"
                min="1"
                max="500"
                value={rowLimit}
                onChange={event => setRowLimit(event.target.value)}
                style={databricksFieldStyle()}
              />
            </label>

            <div className="databricks-summary-grid" style={{
              display: 'grid',
              gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
              gap: 10,
              marginTop: 16,
            }}>
              <DatabricksInfoTile label="Host" value={parsed.host || 'Invalid'} color={primary}/>
              <DatabricksInfoTile label="Warehouse" value={parsed.warehouseId || 'Missing'} color="#38BDF8"/>
              <DatabricksInfoTile label="Schema" value={parsed.schema || 'default'} color="#22C55E"/>
            </div>

            {parsed.error && (
              <div style={databricksNoticeStyle('#EF4444')}>
                {parsed.error}
              </div>
            )}

            <div style={{
              marginTop: 14,
              padding: '12px 13px',
              borderRadius: 14,
              background: 'rgba(56,189,248,0.08)',
              border: '1px solid rgba(56,189,248,0.18)',
              color: 'rgba(var(--theme-text-rgb),0.72)',
              fontSize: 13,
              lineHeight: 1.55,
            }}>
              Use a token with SQL Warehouse access. Start with a SELECT query before trying any write operation.
            </div>
          </section>

          <section className="databricks-card" style={databricksCardStyle()}>
            <div style={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'space-between',
              gap: 12,
              marginBottom: 16,
            }}>
              <div>
                <h2 style={{ margin: 0, color: 'var(--theme-strong)', fontSize: 22 }}>SQL runner</h2>
                <div style={{ marginTop: 4, color: 'rgba(var(--theme-text-rgb),0.54)', fontSize: 13 }}>
                  Executes through /api/databricks/query.
                </div>
              </div>
              <button
                type="button"
                onClick={() => setStatement(DEFAULT_DATABRICKS_QUERY)}
                style={deButtonStyle(primary, false)}
              >
                Smoke query
              </button>
            </div>

            <label style={databricksLabelStyle()}>
              Statement
              <textarea
                value={statement}
                onChange={event => setStatement(event.target.value)}
                spellCheck="false"
                rows={13}
                style={{
                  ...databricksFieldStyle(),
                  resize: 'vertical',
                  lineHeight: 1.55,
                  fontFamily: 'Consolas, "Liberation Mono", monospace',
                  fontSize: 13,
                }}
              />
            </label>

            {error && (
              <div style={databricksNoticeStyle('#EF4444')}>
                {error}
              </div>
            )}

            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginTop: 16 }}>
              <button type="submit" disabled={!canRun} style={{
                ...deButtonStyle(primary, true),
                opacity: canRun ? 1 : 0.55,
              }}>
                {loading ? 'Running...' : 'Run SQL'}
              </button>
              <button
                type="button"
                onClick={() => {
                  setResult(null);
                  setError('');
                }}
                style={deButtonStyle(primary, false)}
              >
                Clear
              </button>
            </div>
          </section>

          <section className="databricks-card databricks-result-card" style={{
            ...databricksCardStyle(),
            gridColumn: '1 / -1',
          }}>
            <DatabricksResultTable result={result} loading={loading} color={primary}/>
          </section>
        </form>
      </div>
    </main>
  );
}

function parseDatabricksJdbcUrlPreview(value) {
  const jdbcUrl = String(value || '').trim();
  const prefix = 'jdbc:databricks://';
  if (!jdbcUrl.toLowerCase().startsWith(prefix)) {
    throw new Error('JDBC URL must start with jdbc:databricks://');
  }

  const [authorityAndPath, ...parts] = jdbcUrl.slice(prefix.length).split(';');
  const url = new URL(`https://${authorityAndPath}`);
  const params = {};
  parts.forEach(part => {
    const separator = part.indexOf('=');
    if (separator === -1) return;
    params[part.slice(0, separator).trim().toLowerCase()] = part.slice(separator + 1).trim();
  });

  const httpPath = params.httppath || '';
  const warehouseMatch = httpPath.match(/\/sql\/1\.0\/warehouses\/([^/?;]+)/i);
  if (!warehouseMatch) throw new Error('Missing SQL warehouse id in httpPath');

  return {
    host: url.hostname,
    port: url.port || '443',
    schema: decodeURIComponent(url.pathname.replace(/^\/+/, '').split('/')[0] || 'default'),
    warehouseId: warehouseMatch[1],
    httpPath,
  };
}

function DatabricksInfoTile({ label, value, color }) {
  return (
    <div style={{
      minWidth: 0,
      padding: '12px 11px',
      borderRadius: 15,
      background: 'rgba(var(--theme-bg-rgb),0.34)',
      border: `1px solid ${color}26`,
    }}>
      <div style={{
        color,
        fontSize: 10,
        fontWeight: 900,
        letterSpacing: '1.4px',
        textTransform: 'uppercase',
        marginBottom: 7,
      }}>{label}</div>
      <div style={{
        color: 'var(--theme-strong)',
        fontSize: 12,
        fontWeight: 800,
        lineHeight: 1.35,
        overflowWrap: 'anywhere',
      }}>{value}</div>
    </div>
  );
}

function DatabricksResultTable({ result, loading, color }) {
  const columns = result?.columns || [];
  const rows = result?.rows || [];

  if (loading) {
    return (
      <div style={databricksEmptyResultStyle()}>
        Running statement through Databricks SQL Warehouse...
      </div>
    );
  }

  if (!result) {
    return (
      <div style={databricksEmptyResultStyle()}>
        Result table will appear here after a successful query.
      </div>
    );
  }

  return (
    <div>
      <div className="databricks-result-head" style={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        gap: 14,
        marginBottom: 14,
      }}>
        <div>
          <h2 style={{ margin: 0, color: 'var(--theme-strong)', fontSize: 22 }}>Result</h2>
          <div style={{ marginTop: 5, color: 'rgba(var(--theme-text-rgb),0.56)', fontSize: 13 }}>
            Statement ID: {result.statementId || 'n/a'}
          </div>
        </div>
        <div style={{
          display: 'inline-flex',
          alignItems: 'center',
          gap: 8,
          padding: '9px 12px',
          borderRadius: 999,
          background: `${color}14`,
          border: `1px solid ${color}30`,
          color,
          fontWeight: 900,
          fontSize: 12,
          whiteSpace: 'nowrap',
        }}>
          {result.rowCount} row{result.rowCount === 1 ? '' : 's'}
        </div>
      </div>

      {result.truncated && (
        <div style={databricksNoticeStyle('#F59E0B')}>
          Databricks truncated this result. Lower the row limit or narrow the SQL.
        </div>
      )}

      {rows.length === 0 || columns.length === 0 ? (
        <div style={databricksEmptyResultStyle()}>
          Query succeeded, but no inline rows were returned.
        </div>
      ) : (
        <div style={{
          width: '100%',
          overflowX: 'auto',
          borderRadius: 16,
          border: '1px solid rgba(var(--theme-text-rgb),0.08)',
        }}>
          <table style={{
            width: '100%',
            borderCollapse: 'collapse',
            minWidth: Math.max(680, columns.length * 160),
            fontSize: 13,
          }}>
            <thead>
              <tr>
                {columns.map(column => (
                  <th key={column.name} style={{
                    padding: '12px 13px',
                    textAlign: 'left',
                    background: 'rgba(var(--theme-bg-rgb),0.5)',
                    color,
                    borderBottom: '1px solid rgba(var(--theme-text-rgb),0.09)',
                    fontWeight: 900,
                    whiteSpace: 'nowrap',
                  }}>
                    {column.name}
                    {column.type && (
                      <span style={{ color: 'rgba(var(--theme-text-rgb),0.42)', fontWeight: 700 }}>
                        {' '}{column.type}
                      </span>
                    )}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {rows.map((row, rowIndex) => (
                <tr key={rowIndex}>
                  {columns.map((column, columnIndex) => (
                    <td key={`${rowIndex}-${column.name}`} style={{
                      padding: '11px 13px',
                      color: 'rgba(var(--theme-text-rgb),0.78)',
                      borderBottom: rowIndex === rows.length - 1 ? 'none' : '1px solid rgba(var(--theme-text-rgb),0.06)',
                      verticalAlign: 'top',
                      overflowWrap: 'anywhere',
                    }}>
                      {row[columnIndex] === null || row[columnIndex] === undefined ? 'NULL' : String(row[columnIndex])}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function DatabricksIcon({ size = 20 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
      stroke="currentColor" strokeWidth="2.1" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
      <path d="M12 3l8 4-8 4-8-4 8-4z"/>
      <path d="M4 12l8 4 8-4"/>
      <path d="M4 17l8 4 8-4"/>
    </svg>
  );
}

function databricksCardStyle() {
  return {
    minWidth: 0,
    padding: 22,
    borderRadius: 22,
    background: 'rgba(var(--theme-surface-rgb),0.22)',
    border: '1px solid rgba(var(--theme-text-rgb),0.08)',
    boxShadow: '0 18px 50px rgba(0,0,0,0.14)',
  };
}

function databricksLabelStyle() {
  return {
    display: 'flex',
    flexDirection: 'column',
    gap: 8,
    color: 'rgba(var(--theme-text-rgb),0.62)',
    fontSize: 12,
    fontWeight: 800,
    letterSpacing: '1.2px',
    textTransform: 'uppercase',
    marginTop: 13,
  };
}

function databricksFieldStyle() {
  return {
    width: '100%',
    minWidth: 0,
    padding: '12px 13px',
    borderRadius: 13,
    border: '1px solid rgba(var(--theme-text-rgb),0.1)',
    background: 'rgba(var(--theme-bg-rgb),0.42)',
    color: 'var(--theme-text)',
    fontFamily: 'Poppins, sans-serif',
    fontSize: 14,
    outline: 'none',
    textTransform: 'none',
    letterSpacing: 0,
  };
}

function databricksNoticeStyle(color) {
  return {
    marginTop: 14,
    padding: '11px 12px',
    borderRadius: 13,
    background: `${color}12`,
    border: `1px solid ${color}2e`,
    color,
    fontSize: 13,
    lineHeight: 1.5,
    fontWeight: 700,
  };
}

function databricksEmptyResultStyle() {
  return {
    minHeight: 132,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    padding: 18,
    borderRadius: 16,
    background: 'rgba(var(--theme-bg-rgb),0.3)',
    border: '1px dashed rgba(var(--theme-text-rgb),0.14)',
    color: 'rgba(var(--theme-text-rgb),0.52)',
    textAlign: 'center',
    fontSize: 14,
  };
}
