/* ============================================================
   Paella — AI-подбор блюд (на реальных данных)
   Ранжируем реальные блюда: оценки гостей + отзывы + состав/цена.
   ============================================================ */

const AI_LIKES = ["Люблю пасту", "Люблю мясо", "Люблю завтраки", "Люблю десерты", "Люблю морепродукты", "Люблю азиатскую кухню", "Люблю грузинскую кухню", "Хочу что-то лёгкое", "Хочу сытно", "Хочу красиво для фото"];
const AI_DISLIKES = ["Не люблю острое", "Не люблю жирное", "Не люблю сладкое", "Не хочу дорого", "Не люблю тяжёлую еду", "Без морепродуктов", "Без мяса"];
const AI_SCENARIOS = ["Быстрый обед", "Завтрак", "Ужин", "Свидание", "Встреча с друзьями", "Деловая встреча", "Хочу попробовать новое"];
const AI_BUDGETS = [["500", "До 500 ₽"], ["700", "До 700 ₽"], ["1000", "До 1000 ₽"], ["1500", "До 1500 ₽"], ["any", "Бюджет не важен"]];
const AI_MOODS = ["Легко", "Сытно", "Премиально", "Домашне", "Остро", "Сладко", "Необычно", "Без риска", "Для фото"];

const LIKE_CATS = {
  "Люблю пасту": ["Паста"],
  "Люблю мясо": ["Стейки", "Мясо", "Бургеры", "Грузинская кухня"],
  "Люблю завтраки": ["Завтраки", "Кофе"],
  "Люблю десерты": ["Десерты"],
  "Люблю морепродукты": ["Морепродукты", "Суши"],
  "Люблю азиатскую кухню": ["Суши"],
  "Люблю грузинскую кухню": ["Грузинская кухня"],
};

const AI_SEAFOOD = /креветк|лосос|тунец|краб|устриц|гребеш|мидии|осьминог|кальмар|рыба|дорадо|сибас|икра|угор|форел|севиче|морепродукт/i;
const AI_MEAT = /стейк|говядин|свинин|бекон|ребр|котлет|бургер|шашлык|каре|ягн[её]н|утка|телятин|курин|цыпл|мясо|пельмен|хинкал|люля/i;
const AI_SWEET = /десерт|чизкейк|тирамису|эклер|наполеон|медовик|мороженое|круассан|павлова|шоколад|панна|сладк/i;
const AI_SPICY = /остр|чили|спайси|том.?ям|кимчи|перчик|халапень|карри/i;
const AI_PREMIUM = /трюфел|краб|фуа|вагю|устриц|икра|лосос|тунец|гребеш|пармезан|том.?ям|стейк|рибай|угор|мрамор|медальон/i;
const AI_COMFORT = /борщ|каша|пюре|сырник|пельмен|вареник|котлет|суп|оладь|блин|хачапур|хинкал|рагу|гуляш|домашн/i;
const AI_FRESH = /салат|боул|севиче|тартар|карпаччо|поке|овощ|грин|спарж/i;
const _normAI = (s) => (s || "").toLowerCase().replace(/ё/g, "е");

function computeAI(prefs, dishes) {
  const likes = new Set(prefs.likes), dis = new Set(prefs.dislikes), moods = new Set(prefs.moods);
  const ft = _normAI(prefs.freeText || "");

  const likedCats = new Set();
  likes.forEach(l => (LIKE_CATS[l] || []).forEach(c => likedCats.add(c)));
  if (/паст|карбонар|спагетт|лазань|ньокк/.test(ft)) likedCats.add("Паста");
  if (/пицц/.test(ft)) likedCats.add("Пицца");
  if (/суши|ролл|сашими|нигир/.test(ft)) likedCats.add("Суши");
  if (/стейк|мяс|говядин|бургер/.test(ft)) { likedCats.add("Стейки"); likedCats.add("Мясо"); }
  if (/завтрак|сырник|омлет|яйц|шакшук/.test(ft)) likedCats.add("Завтраки");
  if (/суп|том.?ям|борщ|рамен|уха/.test(ft)) likedCats.add("Супы");
  if (/салат|боул|поке/.test(ft)) likedCats.add("Салаты");
  if (/десерт|сладк|тирамису|чизкейк/.test(ft)) likedCats.add("Десерты");
  if (/хачапур|хинкал|грузин/.test(ft)) likedCats.add("Грузинская кухня");
  if (/морепродукт|креветк|рыб|лосос|устриц/.test(ft)) likedCats.add("Морепродукты");
  const ftWords = ft.split(/\s+/).filter(w => w.length >= 4);

  const wantPhoto = likes.has("Хочу красиво для фото") || moods.has("Для фото");
  const budget = prefs.budget === "any" ? null : +prefs.budget;
  const scen = prefs.scenario;

  // жёсткие исключения по диете
  let base = dishes.filter(d => {
    const nm = d.name || "";
    if (dis.has("Без морепродуктов") && (d.cat === "Морепродукты" || d.cat === "Суши" || AI_SEAFOOD.test(nm))) return false;
    if (dis.has("Без мяса") && (d.cat === "Стейки" || d.cat === "Мясо" || d.cat === "Бургеры" || AI_MEAT.test(nm))) return false;
    return true;
  });

  let pool = base.slice();
  if (budget) pool = pool.filter(d => d.price && d.price <= budget);
  let fallback = false;
  if (pool.length < 6) { fallback = true; pool = base.slice(); }

  const scored = pool.map(d => {
    let s = 0; const matched = [];
    const nm = d.name || "";
    if (likedCats.has(d.cat)) { s += 28; matched.push("любимая категория"); }
    if (ftWords.length && ftWords.some(w => _normAI(nm).includes(w))) { s += 16; matched.push("по вашему запросу"); }

    // реальные сигналы качества
    if (d.ratingPct != null) { s += (d.ratingPct - 82) * 0.7; matched.push(`оценка гостей ${d.ratingPct}%`); if (d.ratingPct >= 92) s += 8; }
    else if (d.reviewMentions >= 3) { s += 6 + Math.min(d.reviewMentions, 12); matched.push("хвалят в отзывах"); }
    else { s += (d.score - 84) * 0.8; } // d.score — Paella Score 2.0, шкала 0–100

    if (d.photo) { s += 5; if (wantPhoto) { s += 16; matched.push("есть реальное фото"); } }

    // настроение
    if (moods.has("Премиально") && (AI_PREMIUM.test(nm) || (d.price && d.price >= 1500))) { s += 12; matched.push("премиально"); }
    if (moods.has("Сладко") && (d.cat === "Десерты" || AI_SWEET.test(nm))) { s += 12; matched.push("сладко"); }
    if (moods.has("Остро") && AI_SPICY.test(nm)) { s += 10; matched.push("остро"); }
    if (moods.has("Домашне") && AI_COMFORT.test(nm)) { s += 10; matched.push("по-домашнему"); }
    if (moods.has("Легко") && (d.cat === "Салаты" || AI_FRESH.test(nm))) { s += 10; matched.push("легко"); }
    if (moods.has("Сытно") && ["Стейки", "Мясо", "Паста", "Бургеры", "Грузинская кухня"].includes(d.cat)) { s += 8; matched.push("сытно"); }
    if (moods.has("Необычно") && (AI_PREMIUM.test(nm) || /тартар|севиче|карпаччо|фуа|том.?ям|мисо|кимчи/i.test(nm))) { s += 8; matched.push("необычно"); }
    if (moods.has("Без риска") && d.ratingPct != null && d.ratingPct >= 90) { s += 12; matched.push("без риска"); }

    // сценарий
    if (scen === "Свидание" && (AI_PREMIUM.test(nm) || d.cat === "Десерты" || (d.price && d.price >= 900))) s += 8;
    if (scen === "Завтрак" && (d.cat === "Завтраки" || d.cat === "Кофе")) { s += 12; matched.push("на завтрак"); }
    if ((scen === "Быстрый обед" || scen === "Деловая встреча") && d.price && d.price <= 800) s += 6;
    if (scen === "Хочу попробовать новое" && AI_PREMIUM.test(nm)) s += 6;

    // бюджет
    if (budget) { if (d.price && d.price <= budget) { s += 10; if (!fallback) matched.push("в бюджете"); } else s -= 14; }

    // не нравится
    if (dis.has("Не хочу дорого") && d.price) s -= d.price / 150;
    if (dis.has("Не люблю острое") && AI_SPICY.test(nm)) s -= 22;
    if (dis.has("Не люблю сладкое") && (d.cat === "Десерты" || AI_SWEET.test(nm))) s -= 18;
    if (dis.has("Не люблю жирное") && /жарен|фри|жирн|сливочн|сыр|бекон|майонез/i.test(nm)) s -= 8;
    if (dis.has("Не люблю тяжёлую еду")) { if (["Стейки", "Мясо", "Бургеры"].includes(d.cat)) s -= 8; if (d.cat === "Салаты") s += 6; }

    s += (d.reviewMentions || 0) * 0.2;

    const pct = Math.round(Math.max(70, Math.min(98, 72 + s * 0.4)));
    const mm = [...new Set(matched)].slice(0, 5);
    const note = d.reviewSnippet ? `«${d.reviewSnippet}»` : null;
    return { dish: d, pct, matched: mm, note, _s: s };
  });

  scored.sort((a, b) => b._s - a._s || b.dish.q - a.dish.q);
  return { results: scored.slice(0, 7), fallback };
}

function aiWhy(r) {
  const m = r.matched, parts = [];
  if (m.includes("любимая категория")) parts.push("это любимая категория");
  if (m.includes("по вашему запросу")) parts.push("совпадает с вашим запросом");
  const tasteWords = m.filter(x => ["сладко", "остро", "легко", "сытно", "премиально", "по-домашнему", "необычно", "на завтрак"].includes(x));
  if (tasteWords.length) parts.push("по настроению (" + tasteWords.join(", ") + ")");
  const guest = m.find(x => x.startsWith("оценка гостей"));
  if (guest) parts.push(guest);
  else if (m.includes("хвалят в отзывах")) parts.push("его хвалят в отзывах");
  if (m.includes("в бюджете")) parts.push("в бюджете");
  if (m.includes("есть реальное фото")) parts.push("с реальным фото");
  return parts.length ? "Подходит вам — " + parts.slice(0, 3).join(", ") + "." : "Хороший вариант с надёжной оценкой рядом.";
}

function AICard({ r, ctx, onReject, onSimilar }) {
  const d = r.dish;
  const saved = ctx.saved.has(d.id);
  return (
    <article className="aicard">
      <div className="aicard-media" onClick={() => ctx.openDish(d)} style={{ cursor: "pointer", position: "relative", background: "var(--bg-2)" }}>
        <DishPhoto src={d.photo} alt={d.name} size="lg" />
        <ScoreTag u={uOf(d)} float />
      </div>
      <div className="aicard-body">
        <div className="aicard-head">
          <div style={{ minWidth: 0, cursor: "pointer" }} onClick={() => ctx.openDish(d)}>
            <div style={{ fontSize: 17, fontWeight: 800, letterSpacing: "-0.02em", lineHeight: 1.15 }}>{d.name}</div>
            <div className="dcard-meta" style={{ fontSize: 12.5, marginTop: 3 }}>
              <span style={{ fontWeight: 600, color: "var(--ink)" }}>{d.restaurantName}</span><span className="dot"></span><span>{d.district}</span>
            </div>
            <div style={{ fontSize: 16, fontWeight: 800, marginTop: 6 }}>{d.price ? `${d.price} ₽` : "—"}</div>
          </div>
          <div style={{ textAlign: "center", flex: "none" }}>
            <div className="ringm" style={{ "--p": r.pct }}><i>{r.pct}%</i></div>
            <div className="aimatch-cap">совпадение</div>
          </div>
        </div>
        <div className="ai-why"><b>Почему подходит:</b> {aiWhy(r)}</div>
        {r.matched.length > 0 && (
          <div className="ai-matched">{r.matched.map((m, i) => <span className="badge b-olive" key={i}>{m}</span>)}</div>
        )}
        {r.note && (
          <div className="ai-risk" style={{ background: "var(--green-soft, #e9efde)", color: "var(--ink-2)" }}><Icon name="message" size={14} />Из отзывов: {r.note}</div>
        )}
        <div className="ai-actions">
          <button className="btn btn-pri btn-sm" onClick={() => ctx.openDish(d)}>Открыть блюдо</button>
          <button className={"btn btn-sm " + (saved ? "btn-dark" : "btn-soft")} onClick={() => ctx.toggleSave(d.id)}>
            <Icon name="bookmark" size={15} fill={saved ? "currentColor" : "none"} />{saved ? "Сохранено" : "Сохранить"}
          </button>
          <button className="btn btn-soft btn-sm" onClick={() => onSimilar(d)}>Хочу похожие</button>
          <button className="btn btn-ghost btn-sm" onClick={() => onReject(d.id)}>Не подходит</button>
        </div>
      </div>
    </article>
  );
}

const LOAD_STEPS = ["Paella анализирует ваши предпочтения…", "Сравниваем реальные блюда, оценки и отзывы…", "Подбираем лучшие варианты…"];

function AIScreen({ ctx }) {
  const P = window.PAELLA;
  const [freeText, setFreeText] = useState("");
  const [likes, setLikes] = useState([]);
  const [dislikes, setDislikes] = useState([]);
  const [scenario, setScenario] = useState(null);
  const [budget, setBudget] = useState("any");
  const [moods, setMoods] = useState([]);
  const [phase, setPhase] = useState("form"); // form | loading | result
  const [out, setOut] = useState({ results: [], fallback: false });
  const [step, setStep] = useState(0);

  const tgl = (setter, arr) => (v) => setter(arr.includes(v) ? arr.filter(x => x !== v) : [...arr, v]);

  const run = (prefsOverride) => {
    const prefs = prefsOverride || { freeText, likes, dislikes, scenario, budget, moods };
    setPhase("loading"); setStep(0);
    let i = 0;
    const iv = setInterval(() => { i++; if (i < LOAD_STEPS.length) setStep(i); }, 620);
    setTimeout(() => {
      clearInterval(iv);
      setOut(computeAI(prefs, P.dishes));
      setPhase("result");
      paellaScrollTo(0);
    }, 1700);
  };

  const reject = (id) => setOut((o) => ({ ...o, results: o.results.filter(r => r.dish.id !== id) }));
  const similar = (d) => {
    const pool = P.dishes.filter(x => x.cat === d.cat && x.id !== d.id)
      .sort((a, b) => b.q - a.q).slice(0, 7)
      .map(x => ({ dish: x, pct: Math.round(Math.max(76, Math.min(97, 72 + (x.ratingPct != null ? (x.ratingPct - 80) * 0.5 : (x.score - 80) * 0.75)))), matched: ["похоже на «" + d.name + "»", "любимая категория"], note: x.reviewSnippet ? `«${x.reviewSnippet}»` : null }));
    setOut({ results: pool, fallback: false });
    paellaScrollTo(0);
  };
  const reset = () => setPhase("form");

  // ---------- loading ----------
  if (phase === "loading") {
    return (
      <div className="fadein wrap" style={{ maxWidth: 680 }}>
        <div className="ai-loading">
          <div className="ai-spin"></div>
          <div className="ai-step">{LOAD_STEPS[step]}</div>
          <div className="ai-substep">{P.dishes.length.toLocaleString("ru-RU")} реальных блюд в анализе</div>
        </div>
      </div>
    );
  }

  // ---------- results ----------
  if (phase === "result") {
    return (
      <div className="fadein wrap" style={{ maxWidth: 880 }}>
        <div className="pintro" style={{ paddingBottom: 0 }}>
          <span className="eyebrow"><Icon name="sparkles" size={13} style={{ verticalAlign: "-2px", marginRight: 4 }} />AI-подбор</span>
          <h1>Мы подобрали {out.results.length} {plural(out.results.length, "блюдо", "блюда", "блюд")} для вас</h1>
          <p>Реальные блюда с объяснением: почему каждое подходит именно вам — по вкусу, бюджету, оценкам гостей и отзывам.</p>
        </div>
        <div className="row" style={{ gap: 10, margin: "18px 0", flexWrap: "wrap" }}>
          <button className="btn btn-soft btn-sm" onClick={reset}><Icon name="sliders" size={16} />Изменить параметры</button>
          <button className="btn btn-soft btn-sm" onClick={() => run()}><Icon name="sparkles" size={16} />Подобрать заново</button>
        </div>

        {out.fallback && (
          <div className="note" style={{ marginBottom: 16 }}>
            Под все условия точных совпадений мало — показываем близкие варианты. Можно расширить бюджет или убрать часть ограничений.
          </div>
        )}

        {out.results.length === 0 ? (
          <EmptyState emoji="🤔" title="Слишком строгие условия" text="Попробуйте убрать часть ограничений — и Paella найдёт подходящие блюда." />
        ) : (
          <div style={{ display: "grid", gap: 16 }}>
            {out.results.map((r) => <AICard key={r.dish.id} r={r} ctx={ctx} onReject={reject} onSimilar={similar} />)}
          </div>
        )}

        <div className="m-col hot" style={{ marginTop: 26, padding: 24 }}>
          <span className="eyebrow">Как Paella объясняет рекомендацию</span>
          <p style={{ fontSize: 15, lineHeight: 1.55, color: "var(--ink)", margin: "10px 0 0" }}>
            Мы не просто показываем блюдо с высокой оценкой. Мы объясняем, <b>почему оно может подойти именно вам</b> — по вкусу, бюджету, категории и реальным оценкам гостей и отзывам.
          </p>
        </div>

        <div className="note" style={{ marginTop: 16 }}>
          Подбор работает на реальных данных: меню, цены и фото блюд, оценки гостей (Яндекс.Еда) и обработанные отзывы (2ГИС). В будущей версии добавятся персональная история, геолокация и обучение на ваших оценках.
        </div>
      </div>
    );
  }

  // ---------- form ----------
  return (
    <div className="fadein wrap" style={{ maxWidth: 760 }}>
      <section className="sec" style={{ marginTop: 18 }}>
        <div className="ai-hero">
          <span className="pill"><Icon name="sparkles" size={15} />Умный подбор</span>
          <h1>AI-подбор блюд</h1>
          <p>Расскажи, что тебе нравится, а Paella предложит реальные блюда, которые с большей вероятностью подойдут именно тебе. Учитываем вкус, бюджет, категорию, оценки гостей, отзывы и ситуацию.</p>
        </div>
      </section>

      <div className="panel" style={{ padding: 22, marginTop: 18 }}>
        <div className="ai-form">
          <div className="ai-block">
            <label className="h"><span className="num">1</span>Опишите, что вы любите или не любите</label>
            <textarea value={freeText} onChange={(e) => setFreeText(e.target.value)}
              style={{ width: "100%", fontSize: 15, color: "var(--ink)", background: "var(--surface)", border: "1px solid var(--hairline)", borderRadius: "var(--r-sm)", padding: "12px 14px", minHeight: 90, resize: "vertical" }}
              placeholder="Например: люблю пасту, мясо и хачапури, не люблю слишком острое. Хочу сытно до 1200 ₽."></textarea>
          </div>

          <div className="ai-block">
            <label className="h"><span className="num">2</span>Быстрые предпочтения</label>
            <div className="seg">{AI_LIKES.map(l => <button key={l} className={likes.includes(l) ? "on" : ""} onClick={() => tgl(setLikes, likes)(l)}>{l}</button>)}</div>
          </div>

          <div className="ai-block">
            <label className="h"><span className="num">3</span>Что не нравится</label>
            <div className="seg">{AI_DISLIKES.map(l => <button key={l} className={dislikes.includes(l) ? "on" : ""} onClick={() => tgl(setDislikes, dislikes)(l)}>{l}</button>)}</div>
          </div>

          <div className="ai-block">
            <label className="h"><span className="num">4</span>Сценарий</label>
            <div className="seg">{AI_SCENARIOS.map(l => <button key={l} className={scenario === l ? "on" : ""} onClick={() => setScenario(scenario === l ? null : l)}>{l}</button>)}</div>
          </div>

          <div className="ai-block">
            <label className="h"><span className="num">5</span>Бюджет</label>
            <div className="seg">{AI_BUDGETS.map(([k, l]) => <button key={k} className={budget === k ? "on" : ""} onClick={() => setBudget(k)}>{l}</button>)}</div>
          </div>

          <div className="ai-block">
            <label className="h"><span className="num">6</span>Настроение</label>
            <div className="seg">{AI_MOODS.map(l => <button key={l} className={moods.includes(l) ? "on" : ""} onClick={() => tgl(setMoods, moods)(l)}>{l}</button>)}</div>
          </div>

          <button className="btn btn-pri btn-block" onClick={() => run()}><Icon name="sparkles" size={18} />Подобрать блюда</button>
          <p className="muted center" style={{ fontSize: 12.5, margin: 0 }}>Подбор работает на реальных данных: оценки гостей (Яндекс.Еда) и обработанные отзывы (2ГИС). Где реальных оценок нет — используется прозрачная AI-модель Paella Score.</p>
        </div>
      </div>
    </div>
  );
}

function plural(n, one, few, many) {
  const m10 = n % 10, m100 = n % 100;
  if (m10 === 1 && m100 !== 11) return one;
  if (m10 >= 2 && m10 <= 4 && (m100 < 10 || m100 >= 20)) return few;
  return many;
}

Object.assign(window, { AIScreen, computeAI, plural });
