// ============================================
// Reliq — Scan Setup (4-step wizard)
// ============================================

// ── File validation helpers (uses reliqValidate if loaded, inline fallback) ───
const ALLOWED_EXTS = [".apk", ".aab", ".ipa"];
const MAX_FILE_MB  = 200;
const SCANS_API_BASE = "https://api.reliq.dev";

const validateUploadFile = (f) => {
  if (!f) return "Please select a file.";
  const typeErr = window.reliqValidate
    ? window.reliqValidate.fileType(f.name, ALLOWED_EXTS)
    : (ALLOWED_EXTS.some(e => f.name.toLowerCase().endsWith(e)) ? null : `Invalid file type. Accepted: ${ALLOWED_EXTS.join(", ")}.`);
  if (typeErr) return typeErr;
  const sizeErr = window.reliqValidate
    ? window.reliqValidate.fileSize(f.size, MAX_FILE_MB)
    : (f.size > MAX_FILE_MB * 1024 * 1024 ? `File too large. Maximum is ${MAX_FILE_MB} MB.` : null);
  if (sizeErr) return sizeErr;
  return null;
};

const formatBytes = (bytes) => {
  if (bytes === 0) return "0 B";
  const mb = bytes / (1024 * 1024);
  return mb >= 1 ? `${mb.toFixed(1)} MB` : `${(bytes / 1024).toFixed(0)} KB`;
};

const getCurrentWorkspaceId = () => {
  try {
    const authWorkspaceId = window.reliqAuth?.getCurrentWorkspaceId?.() || "";
    if (authWorkspaceId) return authWorkspaceId;

    const authWorkspace = window.reliqAuth?.getWorkspace?.();
    if (authWorkspace?.id) return authWorkspace.id;

    const session = window.reliqAuth?.getUser?.() || null;
    const sessionWorkspaceId = session?.workspace?.id || session?.data?.workspace?.id || "";
    if (sessionWorkspaceId) return sessionWorkspaceId;

    const storedWorkspaceId = window.reliqWorkspace?.getWorkspace?.()?.id || "";
    return storedWorkspaceId.startsWith("wsp_") ? storedWorkspaceId : "";
  } catch (_) {
    return "";
  }
};

const createWebsiteScanRequest = async (targetUrl) => {
  const workspaceId = getCurrentWorkspaceId();
  if (!workspaceId) throw new Error("Workspace not found. Please sign out and sign in again.");

  let res;
  try {
    const apiBase = window.reliqAuth?.apiBase || SCANS_API_BASE;
    res = await fetch(`${apiBase}/v1/scans/website`, {
      method: "POST",
      credentials: "include",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ workspaceId, targetUrl }),
    });
  } catch (_) {
    throw new Error("Network error — could not queue the website scan.");
  }

  let json;
  try { json = await res.json(); } catch (_) { json = {}; }

  if (!res.ok) {
    throw new Error(json.error?.message || "Could not queue the website scan.");
  }

  return json.data ?? json;
};

const ScanSetup = ({ go }) => {
  const [step, setStep] = React.useState(1);
  const [file, setFile] = React.useState(null);
  const [uploadError, setUploadError] = React.useState(null);
  const [drag, setDrag] = React.useState(false);
  const [dragError, setDragError] = React.useState(false); // red border on invalid drag
  const [stores, setStores] = React.useState({ play: true, app: true });
  const [category, setCategory] = React.useState("Productivity");
  const [rating, setRating] = React.useState("Everyone");
  const [running, setRunning] = React.useState(false);
  const [websiteRunning, setWebsiteRunning] = React.useState(false);
  const [websiteUrl, setWebsiteUrl] = React.useState("");

  // Website readiness scan — no upload required. Mirrors the backend
  // POST /v1/scans/website vertical (release readiness + security headers).
  // Natural input ("nba.com") is normalized to a full URL before it is sent;
  // the backend safeFetch / SSRF checks remain the security boundary.
  const startWebsiteScan = async () => {
    if (websiteRunning) return;
    let normalized;
    try {
      normalized = window.normalizeWebsiteUrl(websiteUrl);
    } catch (err) {
      window.reliqToast?.error(err.message || window.WEBSITE_URL_ERROR || "Enter a valid website, e.g. website.com or https://website.com");
      return;
    }

    setWebsiteRunning(true);
    try {
      const scan = await createWebsiteScanRequest(normalized);
      window.reliqToast?.success("Website readiness scan queued for " + normalized);
      go(scan?.id ? `/scan/${scan.id}` : "/scans");
    } catch (err) {
      window.reliqToast?.error(err.message || "Could not queue the website scan.");
    } finally {
      setWebsiteRunning(false);
    }
  };

  const steps = [
    { n: 1, label: "Upload",   sub: "APK / AAB / IPA" },
    { n: 2, label: "Stores",   sub: "Pick targets" },
    { n: 3, label: "Metadata", sub: "Category + rating" },
    { n: 4, label: "Scan",     sub: "Run diagnostics" },
  ];

  // Real file selection — validates type and size
  const acceptFile = (f) => {
    const err = validateUploadFile(f);
    if (err) {
      setUploadError(err);
      setFile(null);
      window.reliqToast?.error(err, 5000);
      return;
    }
    setUploadError(null);
    const ext  = f.name.split(".").pop().toUpperCase();
    const type = ext === "APK" ? "APK · Android Package" : ext === "AAB" ? "AAB · Android App Bundle" : "IPA · iOS App Archive";
    setFile({ name: f.name, size: formatBytes(f.size), type, rawSize: f.size });
  };

  // Mock file pick (for the "Choose file" button, which can't open real dialog in this prototype)
  const pickFile = () => {
    setFile({ name: "Roamly-1.4.0-release.aab", size: "47.3 MB", type: "AAB · Android App Bundle" });
    setUploadError(null);
  };

  const [scanProgress, setScanProgress] = React.useState({});
  const startScan = () => {
    setRunning(true);
    const checks = ["extract", "play", "app", "ai", "report"];
    const durations = { extract: 400, play: 900, app: 700, ai: 1100, report: 400 };
    let total = 0;
    checks.forEach(k => {
      total += durations[k];
      setTimeout(() => setScanProgress(p => ({ ...p, [k]: true })), total - durations[k] / 2);
    });
    setTimeout(() => go("/scan/scn_2k8x"), total + 300);
  };

  return (
    <AuthLayout
      route="scan/new"
      go={go}
      crumbs={["Workspace", "New Scan"]}
      maxWidth={900}
      actions={<button className="btn btn-sm btn-ghost" onClick={() => go("/dashboard")}>Cancel</button>}
    >
          <div className="page-head">
            <div>
              <h1 className="page-title">New Scan</h1>
              <p className="page-sub">Upload your build. We'll run 38 store-compliance checks in parallel.</p>
            </div>
            <div className="text-mono" style={{fontSize:12, color:"var(--fg-2)"}}>Step {step} of 4</div>
          </div>

          <div className="stepper">
            {steps.map(s => (
              <div key={s.n}
                   className={`step ${step === s.n ? "active" : step > s.n ? "done" : ""}`}
                   onClick={() => s.n < step && setStep(s.n)}>
                <div className="n">{step > s.n ? <Icon name="check" size={12} stroke={2.5} /> : s.n}</div>
                <div>
                  <div className="label">{s.label}</div>
                  <div className="sub">{s.sub}</div>
                </div>
              </div>
            ))}
          </div>

          {/* STEP 1: Upload */}
          {step === 1 && (
            <div className="fade-up">
              {!file ? (
                <>
                  <div
                    className={`uploader ${drag ? "drag" : ""}`}
                    style={dragError ? { borderColor:"var(--red)", background:"var(--red-bg)" } : undefined}
                    onDragOver={e => {
                      e.preventDefault();
                      // Quick preview: check file type during hover
                      const item = e.dataTransfer.items?.[0];
                      if (item && item.kind === "file") {
                        const name = item.getAsFile()?.name || "";
                        const valid = ALLOWED_EXTS.some(ext => name.toLowerCase().endsWith(ext));
                        setDragError(!valid);
                      }
                      setDrag(true);
                    }}
                    onDragLeave={() => { setDrag(false); setDragError(false); }}
                    onDrop={e => {
                      e.preventDefault();
                      setDrag(false);
                      setDragError(false);
                      const dropped = e.dataTransfer.files?.[0];
                      if (dropped) acceptFile(dropped);
                      else pickFile(); // fallback for test environments
                    }}
                    onClick={pickFile}
                  >
                    <div className="ic-big"><Icon name="upload" size={22} /></div>
                    <h3>Drop your build here</h3>
                    <p>APK · AAB · IPA · max 200MB</p>
                    <button className="btn btn-primary">Choose file</button>
                    <div className="types">
                      <span>.APK</span><span>.AAB</span><span>.IPA</span>
                    </div>
                  </div>
                  {uploadError && (
                    <div style={{
                      display:"flex", alignItems:"center", gap:8, marginTop:10,
                      padding:"9px 14px", borderRadius:8,
                      background:"var(--red-bg)", border:"1px solid rgba(239,68,68,0.25)",
                      color:"var(--red)", fontSize:13,
                    }}>
                      <Icon name="alert" size={13} /> {uploadError}
                    </div>
                  )}
                  <div style={{marginTop:28, marginBottom:10, fontFamily:"var(--font-mono)", fontSize:10.5, letterSpacing:"0.14em", textTransform:"uppercase", color:"var(--fg-3)"}}>
                    Or connect a source
                  </div>
                  <div className="connect-grid">
                    {[
                      { ic: "github", nm: "GitHub repo", sb: "auto-build & scan" },
                      { ic: "box", nm: "Expo project", sb: "EAS build URL" },
                      { ic: "cpu", nm: "Bitrise / CI", sb: "via API key" },
                    ].map(c => (
                      <div className="connect-card" key={c.nm}>
                        <div className="ic"><Icon name={c.ic} size={18} /></div>
                        <div>
                          <div className="nm">{c.nm}</div>
                          <div className="sb">{c.sb}</div>
                        </div>
                      </div>
                    ))}
                  </div>

                  {/* Website readiness scan — no upload required */}
                  <div style={{marginTop:28, marginBottom:10, fontFamily:"var(--font-mono)", fontSize:10.5, letterSpacing:"0.14em", textTransform:"uppercase", color:"var(--fg-3)"}}>
                    Or scan a website
                  </div>
                  <div style={{display:"flex", gap:8, alignItems:"center"}}>
                    <input
                      type="text"
                      inputMode="url"
                      autoCapitalize="off"
                      autoCorrect="off"
                      spellCheck={false}
                      value={websiteUrl}
                      onChange={e => setWebsiteUrl(e.target.value)}
                      onKeyDown={e => { if (e.key === "Enter") startWebsiteScan(); }}
                      placeholder="website.com or https://website.com"
                      style={{flex:1, padding:"10px 12px", borderRadius:8, border:"1px solid var(--line-2)", background:"var(--bg-1)", color:"var(--fg-0)", fontSize:13}}
                    />
                    <button className="btn btn-primary" onClick={startWebsiteScan} disabled={websiteRunning} style={{opacity: websiteRunning ? 0.7 : 1}}>
                      <Icon name="globe" size={13} /> {websiteRunning ? "Queueing..." : "Run website scan"}
                    </button>
                  </div>
                  <div style={{fontSize:11.5, color:"var(--fg-3)", marginTop:6}}>
                    Checks release readiness and security headers. No upload required.
                  </div>
                </>
              ) : (
                <div className="card">
                  <div className="card-body" style={{display:"flex", alignItems:"center", gap:16}}>
                    <div style={{
                      width:48, height:48, borderRadius:10,
                      background:"var(--teal-bg)", border:"1px solid rgba(0,212,170,0.3)",
                      display:"grid", placeItems:"center", color:"var(--teal)"
                    }}>
                      <Icon name="package" size={22} />
                    </div>
                    <div style={{flex:1}}>
                      <div style={{fontWeight:500, fontSize:14}}>{file.name}</div>
                      <div className="mono" style={{fontSize:12, color:"var(--fg-2)", marginTop:2}}>{file.type} · {file.size}</div>
                    </div>
                    <Icon name="check-circle" size={18} className="" />
                    <button className="btn btn-sm" onClick={() => setFile(null)}>Replace</button>
                  </div>
                </div>
              )}
              <div style={{display:"flex", justifyContent:"flex-end", marginTop:24}}>
                <button className="btn btn-primary" disabled={!file} style={{opacity: file ? 1 : 0.4}} onClick={() => setStep(2)}>
                  Continue <Icon name="arrow-right" size={13} />
                </button>
              </div>
            </div>
          )}

          {/* STEP 2: Stores */}
          {step === 2 && (
            <div className="fade-up">
              <div className="store-grid">
                <div className={`store-card ${stores.play ? "sel" : ""}`} onClick={() => setStores({...stores, play: !stores.play})}>
                  <div className="check">{stores.play && <Icon name="check" size={12} stroke={3} />}</div>
                  <div className="logo" style={{background:"rgba(52,168,83,0.12)", color:"#5fb46a"}}>
                    <Icon name="android" size={22} />
                  </div>
                  <h3>Google Play Store</h3>
                  <p>Run Google Play Developer Program Policy checks against your APK / AAB.</p>
                  <div className="checks-count">
                    <strong>20 checks</strong> · permissions, privacy, security, content policy
                  </div>
                </div>
                <div className={`store-card ${stores.app ? "sel" : ""}`} onClick={() => setStores({...stores, app: !stores.app})}>
                  <div className="check">{stores.app && <Icon name="check" size={12} stroke={3} />}</div>
                  <div className="logo" style={{background:"rgba(255,255,255,0.05)", color:"var(--fg-1)"}}>
                    <Icon name="apple" size={22} />
                  </div>
                  <h3>Apple App Store</h3>
                  <p>Run App Review Guidelines against your IPA, Info.plist, and privacy manifest.</p>
                  <div className="checks-count">
                    <strong>18 checks</strong> · ATS, entitlements, privacy nutrition, ATT
                  </div>
                </div>
              </div>
              <div style={{display:"flex", justifyContent:"space-between", marginTop:24}}>
                <button className="btn" onClick={() => setStep(1)}>Back</button>
                <button className="btn btn-primary" onClick={() => setStep(3)}>
                  Continue <Icon name="arrow-right" size={13} />
                </button>
              </div>
            </div>
          )}

          {/* STEP 3: Metadata */}
          {step === 3 && (
            <div className="fade-up">
              <div className="card">
                <div className="card-head">
                  <div className="card-title">App declaration</div>
                  <span className="card-sub">Used by content & rating checks</span>
                </div>
                <div className="card-body" style={{display:"grid", gridTemplateColumns:"1fr 1fr", gap:18}}>
                  <div className="field">
                    <label>App category</label>
                    <select value={category} onChange={e => setCategory(e.target.value)}>
                      <option>Productivity</option><option>Social</option><option>Games</option>
                      <option>Education</option><option>Finance</option><option>Health & Fitness</option>
                      <option>Kids</option><option>Lifestyle</option>
                    </select>
                    <div className="hint">Determines which policy subset applies (e.g. Kids has stricter rules).</div>
                  </div>
                  <div className="field">
                    <label>Content rating (declared)</label>
                    <select value={rating} onChange={e => setRating(e.target.value)}>
                      <option>Everyone</option><option>Everyone 10+</option>
                      <option>Teen</option><option>Mature 17+</option><option>Adults Only</option>
                    </select>
                    <div className="hint">We cross-check against signals detected in strings & UI.</div>
                  </div>
                  <div className="field" style={{gridColumn:"1 / -1"}}>
                    <label>Privacy policy URL</label>
                    <input defaultValue="https://roamly.app/privacy" />
                    <div className="hint">Required by both stores. We'll fetch and validate.</div>
                  </div>
                  <div className="field" style={{gridColumn:"1 / -1"}}>
                    <label>Listing copy (paste short + long description)</label>
                    <textarea rows="4" defaultValue="Roamly — your travel companion. Discover, plan and share trips with offline maps, smart itineraries and group voting. The fastest way to plan your next adventure."></textarea>
                    <div className="hint">AI policy review reads this for misleading claims, keyword spam, and impersonation.</div>
                  </div>
                </div>
              </div>
              <div style={{display:"flex", justifyContent:"space-between", marginTop:24}}>
                <button className="btn" onClick={() => setStep(2)}>Back</button>
                <button className="btn btn-primary" onClick={() => setStep(4)}>
                  Continue <Icon name="arrow-right" size={13} />
                </button>
              </div>
            </div>
          )}

          {/* STEP 4: Confirm + run */}
          {step === 4 && !running && (
            <div className="fade-up">
              <div className="card">
                <div className="card-head"><div className="card-title">Ready to scan</div></div>
                <div className="card-body">
                  <div style={{display:"grid", gridTemplateColumns:"140px 1fr", gap:"14px 18px", fontSize:13.5}}>
                    <div className="mono" style={{color:"var(--fg-3)", fontSize:11, letterSpacing:"0.1em", textTransform:"uppercase", alignSelf:"center"}}>BUILD</div>
                    <div>{file?.name || "Roamly-1.4.0-release.aab"} <span className="mono" style={{color:"var(--fg-3)"}}> · 47.3 MB</span></div>

                    <div className="mono" style={{color:"var(--fg-3)", fontSize:11, letterSpacing:"0.1em", textTransform:"uppercase", alignSelf:"center"}}>STORES</div>
                    <div style={{display:"flex", gap:8}}>
                      {stores.play && <StoreChip store="play" />} {stores.app && <StoreChip store="app" />}
                    </div>

                    <div className="mono" style={{color:"var(--fg-3)", fontSize:11, letterSpacing:"0.1em", textTransform:"uppercase", alignSelf:"center"}}>CATEGORY</div>
                    <div>{category} · {rating}</div>

                    <div className="mono" style={{color:"var(--fg-3)", fontSize:11, letterSpacing:"0.1em", textTransform:"uppercase", alignSelf:"center"}}>CHECKS</div>
                    <div className="mono" style={{color:"var(--fg-1)"}}>{(stores.play ? 20 : 0) + (stores.app ? 18 : 0)} static checks · 4 AI policy checks</div>

                    <div className="mono" style={{color:"var(--fg-3)", fontSize:11, letterSpacing:"0.1em", textTransform:"uppercase", alignSelf:"center"}}>ETA</div>
                    <div className="mono">~ 2 min 14 sec · queued in priority lane (Pro plan)</div>
                  </div>
                </div>
              </div>
              <div style={{display:"flex", justifyContent:"space-between", marginTop:24}}>
                <button className="btn" onClick={() => setStep(3)}>Back</button>
                <button className="btn btn-primary btn-lg" onClick={startScan}>
                  <Icon name="scan" size={14} /> Run scan
                </button>
              </div>
            </div>
          )}

          {/* SCANNING STATE */}
          {step === 4 && running && (
            <div className="fade-up">
              <div className="card">
                <div className="card-head">
                  <div style={{display:"flex", alignItems:"center", gap:10}}>
                    <svg width="14" height="14" viewBox="0 0 24 24" style={{animation:"spin 1s linear infinite", color:"var(--teal)"}}>
                      <circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="2.5" fill="none" strokeDasharray="40 60" strokeLinecap="round" />
                    </svg>
                    <div className="card-title">Scanning in progress</div>
                  </div>
                  <span className="card-sub" style={{marginLeft:"auto"}}>Priority lane · Pro plan</span>
                </div>
                <div className="card-body" style={{display:"flex", flexDirection:"column", gap:16}}>
                  {[
                    { k:"extract", label:"Extracting binary & manifest", sub:"APK / AAB decompile, resource extraction" },
                    { k:"play",    label:"Running Google Play checks",   sub:"20 checks — permissions, Data Safety, content policy, security" },
                    { k:"app",     label:"Running Apple App Store checks", sub:"18 checks — ATS, privacy manifest, entitlements, ATT" },
                    { k:"ai",      label:"AI policy review",             sub:"4 AI checks — metadata, misleading claims, impersonation, rating" },
                    { k:"report",  label:"Generating report",            sub:"Scoring, fix plan, SDK inventory, privacy declarations" },
                  ].map((c, i) => {
                    const done = scanProgress[c.k];
                    const active = !done && Object.keys(scanProgress).length === i;
                    return (
                      <div key={c.k} style={{display:"flex", alignItems:"flex-start", gap:14}}>
                        <div style={{
                          width:24, height:24, borderRadius:"50%", flexShrink:0, marginTop:1,
                          display:"grid", placeItems:"center",
                          background: done ? "var(--teal-bg)" : "var(--bg-3)",
                          border: `1px solid ${done ? "var(--teal)" : "var(--line-2)"}`,
                          color: done ? "var(--teal)" : "var(--fg-3)",
                        }}>
                          {done
                            ? <Icon name="check" size={11} stroke={2.5} />
                            : active
                              ? <svg width="10" height="10" viewBox="0 0 24 24" style={{animation:"spin 1s linear infinite"}}><circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="3" fill="none" strokeDasharray="40 60" strokeLinecap="round"/></svg>
                              : <span style={{fontFamily:"var(--font-mono)", fontSize:10}}>{i+1}</span>
                          }
                        </div>
                        <div style={{flex:1}}>
                          <div style={{fontSize:13.5, fontWeight:500, color: done ? "var(--fg-1)" : active ? "var(--fg-0)" : "var(--fg-3)"}}>{c.label}</div>
                          <div style={{fontSize:12, color:"var(--fg-3)", fontFamily:"var(--font-mono)", marginTop:2}}>{c.sub}</div>
                          {active && (
                            <div style={{height:3, background:"var(--bg-3)", borderRadius:2, marginTop:8, overflow:"hidden"}}>
                              <div style={{height:"100%", width:"60%", background:"var(--teal)", borderRadius:2, animation:"sweep 1.2s ease-in-out infinite"}}></div>
                            </div>
                          )}
                        </div>
                      </div>
                    );
                  })}
                </div>
              </div>
            </div>
          )}
    </AuthLayout>
  );
};

Object.assign(window, { ScanSetup });
