const { useState: useStateAC, useEffect: useEffectAC } = React;

function AddCityButton({ onAdd }) {
  const [open, setOpen] = useStateAC(false);
  const [cityInput, setCityInput] = useStateAC('');
  const [loading, setLoading] = useStateAC(false);
  const [error, setError] = useStateAC(null);
  const [preview, setPreview] = useStateAC(null);

  const reset = () => {
    setCityInput(''); setLoading(false); setError(null); setPreview(null);
  };

  const generate = async () => {
    if (!cityInput.trim()) return;
    if (!window.claudeClient.isSignedIn() && window.claudeClient.mode() !== 'host') {
      setError('__signin__');
      return;
    }
    setLoading(true); setError(null); setPreview(null);
    try {
      const prompt = `You are a relocation analyst. The user wants to evaluate "${cityInput.trim()}" as a potential expat hub. Produce a JSON object with accurate estimates.

Schema:
{
  "name": "City name (title case)",
  "country": "Country",
  "lat": number,
  "lng": number,
  "weight": 1 | 2 | 3,  // 1=small, 2=mid, 3=major expat hub
  "costSurvival": number,  // USD/mo bare minimum
  "costComfort": number,   // USD/mo comfortable life
  "costLuxury": number,    // USD/mo high-end
  "vibes": ["remote-work"|"health-wellness"|"fund-raising"|"networking"|"creative"|"foodie"|"off-beaten"|"luxury"],  // pick 1-4 most accurate
  "biome": "mediterranean"|"temperate-atlantic"|"temperate-continental"|"temperate-humid"|"temperate-pampas"|"temperate-boreal"|"subtropical-humid"|"subtropical-coastal"|"subtropical-island"|"tropical-wet"|"tropical-dry"|"tropical-highland"|"jungle-rainforest"|"hot-desert"|"high-altitude"|"subarctic",
  "safety": 0-100,
  "visaFlex": 0-100,
  "internet": 0-100,
  "healthcare": 0-100,
  "englishOk": 0-100,  // how livable in English day-to-day
  "community": 0-100,  // expat community depth
  "pitch": "2-3 sentence honest sales pitch, direct voice, no clichés",
  "tags": ["3-5 short tags like visa names, notable features"]
}

Return ONLY the JSON object. No markdown, no preamble.`;
      const res = await window.claudeClient.complete(prompt);
      const match = res.match(/\{[\s\S]*\}/);
      if (!match) throw new Error('No JSON in response');
      const raw = JSON.parse(match[0]);

      // Validate and sanitize every field — never trust AI output directly
      const clamp = (v, lo, hi, def) => (typeof v === 'number' && isFinite(v)) ? Math.max(lo, Math.min(hi, v)) : def;
      const safeStr = (v, maxLen, def = '') => typeof v === 'string' ? v.replace(/[\x00-\x08\x0E-\x1F]/g, '').slice(0, maxLen) : def;
      const safeArr = (v, allowed, maxItems = 6) => Array.isArray(v)
        ? v.filter(x => typeof x === 'string' && (!allowed || allowed.includes(x))).slice(0, maxItems).map(x => safeStr(x, 60))
        : [];

      const VALID_VIBES = ['remote-work','health-wellness','fund-raising','networking','creative','foodie','off-beaten','luxury'];
      const VALID_BIOMES = ['mediterranean','temperate-atlantic','temperate-continental','temperate-humid','temperate-pampas',
        'temperate-boreal','subtropical-humid','subtropical-coastal','subtropical-island','tropical-wet','tropical-dry',
        'tropical-highland','jungle-rainforest','hot-desert','high-altitude','subarctic'];

      const lat = clamp(raw.lat, -90, 90, null);
      const lng = clamp(raw.lng, -180, 180, null);
      if (lat === null || lng === null) throw new Error('Invalid coordinates returned');

      const data = {
        name: safeStr(raw.name, 100, cityInput.trim()),
        country: safeStr(raw.country, 80, ''),
        lat, lng,
        weight: clamp(raw.weight, 1, 3, 1),
        costSurvival: clamp(raw.costSurvival, 100, 50000, 800),
        costComfort: clamp(raw.costComfort, 100, 100000, 1500),
        costLuxury: clamp(raw.costLuxury, 100, 200000, 3000),
        vibes: safeArr(raw.vibes, VALID_VIBES),
        biome: VALID_BIOMES.includes(raw.biome) ? raw.biome : 'temperate-atlantic',
        safety: clamp(raw.safety, 0, 100, 50),
        visaFlex: clamp(raw.visaFlex, 0, 100, 50),
        internet: clamp(raw.internet, 0, 100, 50),
        healthcare: clamp(raw.healthcare, 0, 100, 50),
        englishOk: clamp(raw.englishOk, 0, 100, 50),
        community: clamp(raw.community, 0, 100, 50),
        pitch: safeStr(raw.pitch, 400, ''),
        tags: safeArr(raw.tags, null, 6),
      };

      // Generate crypto-safe ID
      try {
        const arr = new Uint8Array(6);
        crypto.getRandomValues(arr);
        data.id = 'user-' + Array.from(arr).map(b => b.toString(16).padStart(2,'0')).join('');
      } catch {
        data.id = 'user-' + Date.now().toString(36);
      }
      data.userAdded = true;
      setPreview(data);
    } catch (e) {
      if (e.code === 'QUOTA_EXCEEDED') setError(e.message);
      else setError('Could not generate stats. Try a more specific name (e.g. "Porto, Portugal").');
    }
    setLoading(false);
  };

  const commit = () => {
    if (!preview) return;
    onAdd(preview);
    setOpen(false);
    setTimeout(reset, 300);
  };

  return (
    <>
      <button className="add-city-btn" onClick={() => setOpen(true)}>
        <span className="add-plus">+</span>
        <span className="acb-title">Add your own city</span>
        <span className="acb-sub">Claude generates the stats · compare anywhere</span>
      </button>

      {open && (
        <div className="loc-card-overlay" onClick={() => { setOpen(false); setTimeout(reset, 300); }}>
          <div className="loc-card add-city-card" onClick={e => e.stopPropagation()}>
            <div className="loc-card-head">
              <div>
                <div className="loc-kicker">USER·ADDED HUB</div>
                <h2 className="loc-name">Add a city</h2>
                <div style={{ fontSize: 13, color: 'var(--fg-dim)', marginTop: 8, lineHeight: 1.5 }}>
                  Claude will research it and fill out all the stats so you can compare it alongside the built-in hubs.
                </div>
              </div>
              <button className="close-btn" onClick={() => { setOpen(false); setTimeout(reset, 300); }}>×</button>
            </div>

            <div className="add-city-body">
              <div className="filter-label">City name</div>
              <div className="ask-row" style={{ marginTop: 4 }}>
                <input
                  className="ask-input"
                  placeholder="e.g. Porto, Portugal · Taipei · Zanzibar"
                  value={cityInput}
                  onChange={e => setCityInput(e.target.value)}
                  onKeyDown={e => e.key === 'Enter' && !loading && generate()}
                  disabled={loading || preview}
                  autoFocus
                />
                {!preview && (
                  <button className="ask-btn" onClick={generate} disabled={loading || !cityInput.trim()}>
                    {loading ? '…' : 'Generate →'}
                  </button>
                )}
              </div>

              {loading && (
                <div className="deep-output" style={{ marginTop: 16 }}>
                  <div className="deep-loading"><span/><span/><span/></div>
                  <div style={{ fontSize: 12, color: 'var(--fg-dim)', marginTop: 10, fontFamily: 'IBM Plex Mono' }}>
                    Researching cost of living, visas, climate, community…
                  </div>
                </div>
              )}

              {error && error === '__signin__' && (
                <div style={{ marginTop: 14 }}>
                  <SignInForAI feature="Add City"/>
                </div>
              )}
              {error && error !== '__signin__' && (
                <div style={{ marginTop: 14, padding: 12, border: '1px solid var(--danger)', color: 'var(--danger)', fontSize: 13 }}>
                  {error}
                </div>
              )}

              {preview && (
                <div className="preview-block">
                  <div className="preview-head">
                    <div>
                      <div className="loc-kicker">PREVIEW · CLAUDE ESTIMATE</div>
                      <h3 className="preview-name">{preview.name}<span>, {preview.country}</span></h3>
                      <div className="preview-coord">
                        {preview.lat.toFixed(2)}° {preview.lat >= 0 ? 'N' : 'S'} · {preview.lng.toFixed(2)}° {preview.lng >= 0 ? 'E' : 'W'}
                      </div>
                    </div>
                    <div className="user-badge">USER·ADDED</div>
                  </div>

                  <div className="preview-pitch">{preview.pitch}</div>

                  <div className="preview-costs">
                    <div><span>SURVIVAL</span><b>${preview.costSurvival?.toLocaleString()}</b></div>
                    <div><span>COMFORT</span><b>${preview.costComfort?.toLocaleString()}</b></div>
                    <div><span>LUXURY</span><b>${preview.costLuxury?.toLocaleString()}</b></div>
                  </div>

                  <div className="preview-stats">
                    <StatMini label="Safety" v={preview.safety}/>
                    <StatMini label="Visa" v={preview.visaFlex}/>
                    <StatMini label="Internet" v={preview.internet}/>
                    <StatMini label="Healthcare" v={preview.healthcare}/>
                    <StatMini label="English" v={preview.englishOk}/>
                    <StatMini label="Community" v={preview.community}/>
                  </div>

                  <div className="preview-meta">
                    <div><span>Biome:</span> {preview.biome}</div>
                    <div><span>Vibes:</span> {(preview.vibes || []).join(', ')}</div>
                    {preview.tags?.length > 0 && (
                      <div><span>Tags:</span> {preview.tags.join(' · ')}</div>
                    )}
                  </div>

                  <div className="preview-actions">
                    <button className="deep-btn" onClick={commit}>
                      <span className="ai-dot"/>
                      Add to map & favorites
                    </button>
                    <button className="reset-btn" onClick={() => { setPreview(null); }}>
                      Try again
                    </button>
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
      )}
    </>
  );
}

function StatMini({ label, v }) {
  return (
    <div className="stat-mini">
      <div className="stat-mini-row">
        <span>{label}</span><b>{v}</b>
      </div>
      <div className="statbar-track"><div className="statbar-fill" style={{ width: v + '%' }}/></div>
    </div>
  );
}

window.AddCityButton = AddCityButton;
