// Atlubni Docs — shared components
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// Tiny syntax highlighter — handles cURL, JS, Python, JSON
const tokenize = (code, lang) => {
  // Returns array of {t, k} where k is token kind
  const tokens = [];
  if (lang === "json") {
    const re = /("(?:\\.|[^"\\])*")(\s*:)|("(?:\\.|[^"\\])*")|\b(true|false|null)\b|(-?\d+\.?\d*)|([{}\[\],])|(\s+)|([^"\d\s{}\[\],]+)/g;
    let m;
    while ((m = re.exec(code))) {
      if (m[1]) { tokens.push({t: m[1], k: "key"}); tokens.push({t: m[2], k: "pun"}); }
      else if (m[3]) tokens.push({t: m[3], k: "str"});
      else if (m[4]) tokens.push({t: m[4], k: "kw"});
      else if (m[5]) tokens.push({t: m[5], k: "num"});
      else if (m[6]) tokens.push({t: m[6], k: "pun"});
      else if (m[7]) tokens.push({t: m[7], k: ""});
      else if (m[8]) tokens.push({t: m[8], k: ""});
    }
    return tokens;
  }
  if (lang === "bash" || lang === "curl") {
    const lines = code.split("\n");
    lines.forEach((line, i) => {
      if (i > 0) tokens.push({t: "\n", k: ""});
      // comments
      if (line.trim().startsWith("#")) { tokens.push({t: line, k: "com"}); return; }
      const re = /("(?:\\.|[^"\\])*")|('(?:\\.|[^'\\])*')|(\\$)|(\s-{1,2}[A-Za-z][\w-]*)|(\bcurl\b|\bGET\b|\bPOST\b|\bPUT\b|\bDELETE\b)|(\s+)|([^\s"'\\]+)/g;
      let m;
      while ((m = re.exec(line))) {
        if (m[1] || m[2]) tokens.push({t: m[1] || m[2], k: "str"});
        else if (m[3]) tokens.push({t: m[3], k: "op"});
        else if (m[4]) tokens.push({t: m[4], k: "flag"});
        else if (m[5]) tokens.push({t: m[5], k: "kw"});
        else if (m[6]) tokens.push({t: m[6], k: ""});
        else if (m[7]) tokens.push({t: m[7], k: ""});
      }
    });
    return tokens;
  }
  if (lang === "js" || lang === "ts") {
    const kws = /\b(import|from|export|const|let|var|function|return|if|else|for|while|new|await|async|class|extends|throw|try|catch|of|in)\b/;
    const re = /(\/\/[^\n]*)|(`(?:\\.|[^`\\])*`)|("(?:\\.|[^"\\])*")|('(?:\\.|[^'\\])*')|\b(\d+\.?\d*)\b|([A-Za-z_$][\w$]*)(\s*\()|([A-Za-z_$][\w$]*)|(\s+)|([^\w\s])/g;
    let m;
    while ((m = re.exec(code))) {
      if (m[1]) tokens.push({t: m[1], k: "com"});
      else if (m[2] || m[3] || m[4]) tokens.push({t: m[2] || m[3] || m[4], k: "str"});
      else if (m[5]) tokens.push({t: m[5], k: "num"});
      else if (m[6]) { tokens.push({t: m[6], k: "fn"}); tokens.push({t: m[7] || "(", k: ""}); }
      else if (m[8]) tokens.push({t: m[8], k: kws.test(m[8]) ? "kw" : ""});
      else if (m[9]) tokens.push({t: m[9], k: ""});
      else if (m[10]) tokens.push({t: m[10], k: "pun"});
    }
    return tokens;
  }
  if (lang === "python" || lang === "py") {
    const kws = /\b(import|from|as|def|return|if|else|elif|for|while|class|try|except|with|in|not|and|or|None|True|False|lambda|pass|raise|yield|async|await)\b/;
    const re = /(#[^\n]*)|("""[\s\S]*?""")|("(?:\\.|[^"\\])*")|('(?:\\.|[^'\\])*')|\b(\d+\.?\d*)\b|([A-Za-z_][\w]*)(\s*\()|([A-Za-z_][\w]*)|(\s+)|([^\w\s])/g;
    let m;
    while ((m = re.exec(code))) {
      if (m[1]) tokens.push({t: m[1], k: "com"});
      else if (m[2] || m[3] || m[4]) tokens.push({t: m[2] || m[3] || m[4], k: "str"});
      else if (m[5]) tokens.push({t: m[5], k: "num"});
      else if (m[6]) { tokens.push({t: m[6], k: "fn"}); tokens.push({t: m[7] || "(", k: ""}); }
      else if (m[8]) tokens.push({t: m[8], k: kws.test(m[8]) ? "kw" : ""});
      else if (m[9]) tokens.push({t: m[9], k: ""});
      else if (m[10]) tokens.push({t: m[10], k: "pun"});
    }
    return tokens;
  }
  return [{t: code, k: ""}];
};

const Highlight = ({ code, lang }) => {
  const tokens = useMemo(() => tokenize(code, lang), [code, lang]);
  return <>{tokens.map((tok, i) => tok.k ? <span key={i} className={`tk-${tok.k}`}>{tok.t}</span> : tok.t)}</>;
};

// Code block with tabs and copy
const CodeBlock = ({ samples, label, t }) => {
  // samples = [{lang, name, code}] or single {lang, code}
  const arr = Array.isArray(samples) ? samples : [samples];
  const [tab, setTab] = useState(0);
  const [copied, setCopied] = useState(false);
  const cur = arr[tab];
  const onCopy = () => {
    navigator.clipboard?.writeText(cur.code);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  };
  return (
    <div className="code-block">
      <div className="code-tabs">
        {label && <div className="code-label">{label}</div>}
        {arr.length > 1 && arr.map((s, i) => (
          <button key={i} className={`code-tab ${tab === i ? "active" : ""}`} onClick={() => setTab(i)}>{s.name || s.lang}</button>
        ))}
        {arr.length === 1 && !label && <div className="code-label">{cur.lang}</div>}
        <div className="code-actions">
          <button className={`code-action-btn ${copied ? "copied" : ""}`} onClick={onCopy} aria-label={t.copy}>
            <DocIcon name={copied ? "check" : "copy"} size={12} />
            {copied ? t.copied : t.copy}
          </button>
        </div>
      </div>
      <pre className="code-pre" dir="ltr"><Highlight code={cur.code} lang={cur.lang} /></pre>
    </div>
  );
};

// Callout
const Callout = ({ type = "info", title, children }) => {
  const icons = { info: "info", tip: "sparkles", note: "circle-info", warning: "alert-tri", danger: "alert-oct" };
  return (
    <div className={`callout ${type}`} role={type === "danger" || type === "warning" ? "alert" : "note"}>
      <span className="icon"><DocIcon name={icons[type]} size={16} /></span>
      <div>
        {title && <strong>{title}</strong>}
        <p>{children}</p>
      </div>
    </div>
  );
};

// Param table
const ParamTable = ({ rows, t }) => (
  <table className="param-table">
    <thead><tr><th style={{width: "22%"}}>{t.lang === "ar" ? "الاسم" : "Name"}</th><th>{t.lang === "ar" ? "الوصف" : "Description"}</th></tr></thead>
    <tbody>
      {rows.map((r, i) => (
        <tr key={i}>
          <td><span className="nm">{r.name}{r.required && <span className="req">*</span>}</span></td>
          <td>
            <span className="type-pill">{r.type}</span>
            <span>{r.desc}</span>
          </td>
        </tr>
      ))}
    </tbody>
  </table>
);

// Endpoint card
const Endpoint = ({ method, path, anchor, title, desc, params, request, response, onTryIt, t }) => (
  <div className="endpoint" id={anchor}>
    <div className="endpoint-head">
      <span className={`method ${method.toLowerCase()}`}>{method}</span>
      <span className="path" dir="ltr">{path}</span>
      {title && <span className="endpoint-title">{title}</span>}
    </div>
    {desc && <p className="endpoint-desc">{desc}</p>}
    {params && params.length > 0 && <ParamTable rows={params} t={t} />}
    {(request || response) && (
      <div className="rr-pair">
        {request && (
          <div className="code-block">
            <div className="rr-head">
              <span className={`method ${method.toLowerCase()}`}>{method}</span>
              <span dir="ltr" style={{ marginInlineStart: 4 }}>{path}</span>
            </div>
            <pre className="code-pre" dir="ltr"><Highlight code={request} lang="bash" /></pre>
          </div>
        )}
        {response && (
          <div className="code-block">
            <div className="rr-head">
              <span className="status-pill s2xx">200 OK</span>
              <span style={{ fontFamily: "JetBrains Mono", fontSize: 11, color: "rgba(255,255,255,0.4)", marginInlineStart: "auto" }}>{response.length > 200 ? Math.round(response.length / 12) : 87}ms</span>
            </div>
            <pre className="code-pre" dir="ltr"><Highlight code={response} lang="json" /></pre>
          </div>
        )}
      </div>
    )}
    {onTryIt && (
      <div className="endpoint-actions">
        <button className="btn btn-primary" onClick={onTryIt}>
          <DocIcon name="play" size={12} /> {t.tryIt}
        </button>
      </div>
    )}
  </div>
);

window.tokenize = tokenize;
window.Highlight = Highlight;
window.CodeBlock = CodeBlock;
window.Callout = Callout;
window.ParamTable = ParamTable;
window.Endpoint = Endpoint;
