// Экран приложения: домашний список разборов + дашборд по конкретной встрече.
// Разбор запускается из телеграм-бота, поэтому формы ввода транскрипции здесь нет.
(function () {
  const { useState, useEffect, useMemo } = React as any;
  const T = (window as any).AppTypes;
  const { Badge, Button, Card, Label, Input, Collapsible, Row } = (window as any).UI;
  const { ActionCard, TextList, ConfirmModal, SuccessPanel } = (window as any).Results;

  const KINDS: Array<[string, string]> = [
    ["our_tasks", "our_task"],
    ["customer_commitments", "customer_commitment"],
    ["unclear_actions", "unclear_action"],
  ];

  function loginFor(name: string, team: any[]): string {
    const person = (team || []).filter((p: any) => p.name === name)[0];
    return (person && person.login) || "";
  }

  function buildItemStates(result: any, ourTeam: any[]) {
    const states: Record<string, any> = {};
    KINDS.forEach(([listKey, kind]) => {
      (result[listKey] || []).forEach((item: any) => {
        const dups = (result.potential_duplicates || []).filter((d: any) => d.new_task_id === item.id);
        const likely = dups.find((d: any) => d.level === "likely");
        states[item.id] = {
          kind,
          selected: kind !== "unclear_action",
          mode: likely ? "update" : "create",
          dupId: likely ? likely.existing_task_id : null,
          applied: null,
          fields: {
            queue_key: item.queue_key || null,
            assignee_login: loginFor(item.assignee, ourTeam),
            title: item.title,
            description: item.description,
            assignee: item.assignee || null,
            owner: item.owner || null,
            owner_side: item.owner_side,
            deadline: item.deadline,
            deadline_text: item.deadline_text,
            priority: item.priority || "unknown",
          },
        };
      });
    });
    return states;
  }

  const MONTHS = ["янв", "фев", "мар", "апр", "мая", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"];
  function shortDate(iso: string): string {
    const d = new Date(iso);
    if (isNaN(d.getTime())) return iso || "";
    return d.getDate() + " " + MONTHS[d.getMonth()] + ", " + String(d.getHours()).padStart(2, "0")
      + ":" + String(d.getMinutes()).padStart(2, "0");
  }

  function App() {
    const [health, setHealth] = useState(null as any);
    const [tracker, setTracker] = useState(null as any);
    const [queues, setQueues] = useState([] as any[]);
    const [selectedQueues, setSelectedQueues] = useState([] as string[]);
    const [queueHints, setQueueHints] = useState({} as any);
    const [trackerUsers, setTrackerUsers] = useState([] as any[]);
    const [ourTeam, setOurTeam] = useState([] as any[]);
    const [projectContext, setProjectContext] = useState("");
    const [glossary, setGlossary] = useState([] as any[]);
    const [profile, setProfile] = useState(null as any);
    const [teamSaved, setTeamSaved] = useState(false);
    const [recent, setRecent] = useState([] as any[]);

    const [phase, setPhase] = useState("home");      // home | loading | results
    const [resp, setResp] = useState(null as any);
    const [meta, setMeta] = useState(null as any);
    const [states, setStates] = useState({} as any);
    const [error, setError] = useState("");
    const [confirming, setConfirming] = useState(false);
    const [busy, setBusy] = useState(false);
    const [created, setCreated] = useState(null as any);

    const openAnalysis = (id: string, team: any[]) => {
      setPhase("loading");
      setError("");
      T.getJSON("/api/analysis/" + id).then((item: any) => {
        setResp(item.response);
        setMeta({ id: item.id, title: item.title, created_at: item.created_at });
        const ctx = item.context || {};
        setStates(buildItemStates(item.response.result, (ctx.our_team && ctx.our_team.length) ? ctx.our_team : team));
        setPhase("results");
        window.scrollTo({ top: 0 });
      }).catch((e: any) => {
        setError("Не удалось открыть разбор: " + (e.message || e));
        setPhase("home");
      });
    };

    useEffect(() => {
      const tg = (window as any).Telegram && (window as any).Telegram.WebApp;
      if (tg && tg.initData) { tg.ready(); tg.expand(); }

      // разбор открываем независимо от настроек: упавшие настройки не должны его прятать
      const analysisId = new URLSearchParams(window.location.search).get("analysis");
      T.getJSON("/api/settings")
        .then((s: any) => {
          const team = s.our_team || [];
          setOurTeam(team);
          setProjectContext(s.project_context || "");
          setGlossary(s.glossary || []);
          setProfile(s);
          if (analysisId) openAnalysis(analysisId, team);
        })
        .catch((e: any) => {
          setError(e.message || String(e));
          if (analysisId) openAnalysis(analysisId, []);
        });

      T.getJSON("/api/health").then(setHealth).catch(() => {});
      T.getJSON("/api/analyses?limit=8").then((d: any) => setRecent(d.items || [])).catch(() => {});
      T.getJSON("/api/tracker/status").then((st: any) => {
        setTracker(st);
        if (!st.configured) return;
        T.getJSON("/api/tracker/queues").then((d: any) => {
          setQueues(d.queues || []);
          setSelectedQueues((d.queues || []).map((q: any) => q.key));
        }).catch(() => {});
        T.getJSON("/api/tracker/users").then((d: any) => setTrackerUsers(d.users || [])).catch(() => {});
        T.getJSON("/api/tracker/queue-hints").then((d: any) => setQueueHints(d.hints || {})).catch(() => {});
      }).catch(() => {});
    }, []);

    const saveTeam = async (team: any[]) => {
      setOurTeam(team);
      try {
        await T.postJSON("/api/settings", {
          our_team: team.filter((p: any) => (p.name || "").trim()),
          project_context: projectContext,
          glossary: glossary.filter((t: any) => (t.right || "").trim()),
        });
        setTeamSaved(true);
        window.setTimeout(() => setTeamSaved(false), 1500);
      } catch (e) { /* настройки не критичны для просмотра */ }
    };

    const saveQueueHints = async () => {
      try {
        await T.postJSON("/api/tracker/queue-hints", queueHints);
        const d = await T.getJSON("/api/tracker/queues");
        setQueues(d.queues || []);
      } catch (e) { /* подсказки не критичны */ }
    };

    const patch = (id: string, partial: any) =>
      setStates((prev: any) => ({ ...prev, [id]: { ...prev[id], ...partial } }));

    const plan = useMemo(() => {
      const items: any[] = [];
      const counts: any = { created: 0, updated: 0, report_only: 0, no_queue: 0,
                            our_tasks: 0, customer_commitments: 0, unclear_actions: 0 };
      const trackerOn = !!(tracker && tracker.configured);
      if (!resp) return { items, counts, byQueue: [] };
      KINDS.forEach(([listKey, kind]) => {
        (resp.result[listKey] || []).forEach((item: any) => {
          const st = states[item.id];
          if (!st || !st.selected) return;
          const f = st.fields;
          const isUpdate = st.mode === "update" && st.dupId;
          items.push({
            action: isUpdate ? "update_existing" : "create",
            kind, title: f.title, description: f.description,
            assignee: kind === "customer_commitment" ? f.owner : f.assignee,
            owner_side: f.owner_side, deadline: f.deadline, deadline_text: f.deadline_text,
            priority: f.priority, source_quote: item.source_quote,
            existing_task_id: isUpdate ? st.dupId : null,
            applied_updates: st.applied || null,
            queue_key: f.queue_key || null,
            assignee_login: f.assignee_login || loginFor(f.assignee, ourTeam) || "",
          });
          if (isUpdate) counts.updated += 1;
          else if (trackerOn && f.owner_side !== "OUR_TEAM") counts.report_only += 1;
          else { counts.created += 1; counts[listKey] += 1; }
        });
      });
      counts.no_queue = items.filter((i: any) =>
        i.action === "create" && i.owner_side === "OUR_TEAM" && (tracker && tracker.configured) && !i.queue_key).length;
      const grouped: Record<string, number> = {};
      items.filter((i: any) => i.action === "create" && i.owner_side === "OUR_TEAM")
        .forEach((i: any) => { const k = i.queue_key || ""; grouped[k] = (grouped[k] || 0) + 1; });
      return { items, counts, byQueue: Object.keys(grouped).map((k) => ({ key: k, count: grouped[k] })) };
    }, [resp, states, tracker, ourTeam]);

    const submit = async () => {
      setBusy(true);
      try {
        setCreated(await T.postJSON("/api/create-tasks", { items: plan.items }));
        setConfirming(false);
      } catch (e: any) {
        setError(e.message || String(e));
      } finally {
        setBusy(false);
      }
    };

    // ------------------------------------------------------------ домашний экран

    if (phase !== "results") {
      return (
        <div className="mx-auto max-w-2xl px-4 pb-16 pt-8">
          <header className="px-1">
            <h1 className="text-[26px] font-extrabold leading-tight tracking-tight">Разборы встреч</h1>
            <p className="mt-1 text-[14px] font-medium text-ink-soft">
              Пришлите расшифровку боту — разбор появится здесь.
            </p>
          </header>

          {error ? (
            <div className="mt-5 rounded-2xl bg-rose-100 px-4 py-3 text-sm font-medium text-rose-900">{error}</div>
          ) : null}

          {phase === "loading" ? (
            <Card className="mt-5 px-5 py-6 text-sm font-medium text-ink-soft">Открываю разбор…</Card>
          ) : null}

          <Card className="mt-5 px-5 py-5">
            <Label hint={recent.length ? String(recent.length) : ""}>Последние встречи</Label>
            {recent.length ? (
              <div className="space-y-2">
                {recent.map((item: any) => (
                  <Row key={item.id} title={T.cleanTitle(item.title) || "Встреча"}
                    hint={shortDate(item.created_at) + " · " + (item.source === "telegram" ? "из бота" : "веб")}
                    right={item.tasks + " " + T.plural(item.tasks, "задача", "задачи", "задач")}
                    onClick={() => openAnalysis(item.id, ourTeam)} />
                ))}
              </div>
            ) : (
              <p className="text-sm font-medium leading-relaxed text-ink-mute">
                Пока пусто. Отправьте боту файл с расшифровкой или текст встречи.
              </p>
            )}
          </Card>

          <div className="mt-4 space-y-3">
            <Collapsible title="Команда"
              hint={ourTeam.length ? ourTeam.length + " чел." : "не заполнена"}>
              <p className="mb-3 text-xs font-medium leading-relaxed text-ink-mute">
                Заполняется один раз. Логин нужен, чтобы задача создавалась сразу с исполнителем.
              </p>
              {React.createElement((window as any).UI.TeamEditor, {
                people: ourTeam, onChange: setOurTeam, accent: "bg-ink",
                withLogin: !!(tracker && tracker.configured),
              })}
              <datalist id="tracker-users">
                {trackerUsers.map((u: any) => <option key={u.login} value={u.login}>{u.display}</option>)}
              </datalist>
              <div className="mt-3 flex items-center gap-3">
                <Button variant="primary" className="py-2" onClick={() => saveTeam(ourTeam)}>Сохранить</Button>
                {teamSaved ? <span className="text-xs font-semibold text-ink-soft">сохранено</span> : null}
              </div>
            </Collapsible>

            <Collapsible title="Проект и термины"
              hint={projectContext ? "заполнено" : "поможет точности"}>
              <p className="mb-2 text-xs font-medium leading-relaxed text-ink-mute">
                Чем занимается команда — этот текст уходит в разбор как контекст.
              </p>
              {React.createElement((window as any).UI.Textarea, {
                rows: 3, value: projectContext, placeholder: "Например: умный поиск процедур для Росэлторга, подбор по тегам, интеграции с ГРЛС и ЕИС",
                onChange: (e: any) => setProjectContext(e.target.value),
              })}
              <div className="mt-4">
                <Label hint="расшифровка коверкает названия">Словарь терминов</Label>
                <p className="mb-2 text-xs font-medium leading-relaxed text-ink-mute">
                  «Русулторг» → «Росэлторг». Слева как слышится в записи, справа как правильно.
                  Можно оставить левое поле пустым и просто пояснить аббревиатуру.
                </p>
                {React.createElement((window as any).UI.GlossaryEditor, {
                  terms: glossary, onChange: setGlossary,
                })}
              </div>
              <div className="mt-3">
                <Button variant="primary" className="py-2" onClick={() => saveTeam(ourTeam)}>Сохранить</Button>
              </div>
            </Collapsible>

            <Collapsible title="Очереди трекера"
              hint={queues.length ? queues.length + " шт." : (tracker && tracker.configured ? "" : "трекер не подключён")}>
              {React.createElement((window as any).UI.QueuePicker, {
                tracker, queues, selected: selectedQueues, onChange: setSelectedQueues,
                hints: queueHints, onHintsSave: saveQueueHints,
                onHintChange: (key: string, value: string) =>
                  setQueueHints((prev: any) => ({ ...prev, [key]: value })),
              })}
            </Collapsible>
          </div>

          <div className="mt-6 flex flex-wrap items-center gap-2 px-1">
            {health ? (
              <Badge tone={health.llm_configured ? "lime" : "amber"}>
                {health.llm_configured ? health.model : "без LLM"}
              </Badge>
            ) : null}
            {tracker && tracker.configured ? (
              <Badge tone={tracker.dry_run ? "amber" : "blue"}>
                Трекер · {tracker.dry_run ? "dry-run" : "боевой"}
              </Badge>
            ) : null}
            {tracker && tracker.user ? <Badge tone="slate">задачи от имени: {tracker.user}</Badge> : null}
          </div>
          {profile && profile.id && !profile.tracker_connected ? (
            <p className="mt-3 px-1 text-xs font-medium leading-relaxed text-ink-mute">
              Свой Трекер не подключён — задачи создаются от имени владельца сервиса.
              Отправьте боту команду <span className="font-bold text-ink">/connect</span>,
              чтобы они создавались от вашего.
            </p>
          ) : null}
        </div>
      );
    }

    // ------------------------------------------------------------ разбор встречи

    const r = resp.result;
    const dupsFor = (item: any) => (r.potential_duplicates || []).filter((d: any) => d.new_task_id === item.id);
    const ourNames = ourTeam.map((p: any) => p.name).filter(Boolean);
    const selectedCount = plan.items.length;

    const renderList = (listKey: string, kind: string, empty: string) => {
      const list = r[listKey] || [];
      if (!list.length) return <p className="px-1 text-sm font-medium text-ink-mute">{empty}</p>;
      return (
        <div className="space-y-3">
          {list.map((item: any) => (
            <ActionCard key={item.id} item={item} kind={kind} st={states[item.id]}
              patch={(p: any) => patch(item.id, p)} dups={dupsFor(item)}
              ourNames={ourNames} customerNames={[]}
              queues={queues} tracker={tracker} />
          ))}
        </div>
      );
    };

    const Section = ({ title, count, hint, children }: any) => (
      <section className="mt-7">
        <div className="mb-3 flex items-baseline gap-2 px-1">
          <h2 className="text-[17px] font-extrabold tracking-tight text-ink">{title}</h2>
          {typeof count === "number" ? <span className="text-sm font-bold text-ink-mute">{count}</span> : null}
          {hint ? <span className="text-xs font-medium text-ink-mute">{hint}</span> : null}
        </div>
        {children}
      </section>
    );

    return (
      <div className="mx-auto max-w-2xl px-4 pb-32 pt-8">
        <header className="px-1">
          <button onClick={() => { setPhase("home"); setCreated(null); setError(""); }}
            className="text-[13px] font-semibold text-ink-mute hover:text-ink">← Все встречи</button>
          <h1 className="mt-2 text-[24px] font-extrabold leading-tight tracking-tight">
            {(meta && T.cleanTitle(meta.title)) || "Разбор встречи"}
          </h1>
          <p className="mt-1 text-[13px] font-medium text-ink-mute">
            {({ internal: "внутренняя", customer: "с заказчиком", mixed: "смешанная" } as any)[r.meeting_type] || r.meeting_type}
            {" · "}{resp.meeting_date}
            {resp.chunks > 1 ? " · по " + resp.chunks + " фрагментам" : ""}
            {tracker && tracker.configured ? (tracker.dry_run ? " · dry-run" : " · боевой режим") : ""}
          </p>
        </header>

        {r.meeting_summary ? (
          <Card className="mt-5 px-5 py-4">
            <p className="text-[14px] font-medium leading-relaxed text-ink-soft">{r.meeting_summary}</p>
            {r.meeting_type_reason ? (
              <p className="mt-3 border-t border-black/5 pt-3 text-[12px] font-medium text-ink-mute">
                Тип встречи определён автоматически: {r.meeting_type_reason}
                {r.external_participants && r.external_participants.length
                  ? " Не из вашей команды: " + r.external_participants.join(", ") + "."
                  : ""}
              </p>
            ) : null}
          </Card>
        ) : null}

        {resp.validation_warnings && resp.validation_warnings.length ? (
          <Card className="mt-3 bg-lime-soft px-5 py-4">
            <div className="text-[13px] font-bold text-ink">Что поправлено автоматически</div>
            <ul className="mt-2 space-y-1 text-[13px] font-medium text-ink-soft">
              {resp.validation_warnings.map((w: string, i: number) => <li key={i}>• {w}</li>)}
            </ul>
          </Card>
        ) : null}

        {error ? (
          <div className="mt-4 rounded-2xl bg-rose-100 px-4 py-3 text-sm font-medium text-rose-900">{error}</div>
        ) : null}

        <Section title="Наши задачи" count={r.our_tasks.length}>
          {renderList("our_tasks", "our_task", "Обязательств нашей команды не зафиксировано.")}
        </Section>

        {r.customer_commitments.length ? (
          <Section title="Обязательства заказчика" count={r.customer_commitments.length}
            hint="в трекер не уходят">
            {renderList("customer_commitments", "customer_commitment", "")}
          </Section>
        ) : null}

        {r.unclear_actions.length ? (
          <Section title="Без владельца" count={r.unclear_actions.length} hint="решите, чьё это">
            {renderList("unclear_actions", "unclear_action", "")}
          </Section>
        ) : null}

        <Section title="Решения" count={r.decisions.length}>
          <TextList items={r.decisions} icon="✅" empty="Решений на встрече не зафиксировано." />
        </Section>

        <Section title="Открытые вопросы" count={r.open_questions.length}>
          <TextList items={r.open_questions} icon="❓" empty="Открытых вопросов не осталось." />
        </Section>

        <div className="fixed inset-x-0 bottom-0 bg-gradient-to-t from-canvas via-canvas to-transparent pb-4 pt-6">
          <div className="mx-auto flex max-w-2xl items-center justify-between gap-3 px-4">
            <div className="text-[13px] font-semibold text-ink-soft">
              Выбрано {selectedCount}
              {plan.counts.updated ? <span className="text-ink-mute"> · обновим {plan.counts.updated}</span> : null}
            </div>
            <Button variant="primary" disabled={!selectedCount} onClick={() => setConfirming(true)}
              className="px-6 py-3">
              Создать задачи
            </Button>
          </div>
        </div>

        {confirming ? (
          <ConfirmModal plan={plan} busy={busy} tracker={tracker}
            onCancel={() => setConfirming(false)} onConfirm={submit} />
        ) : null}
        {created ? <SuccessPanel data={created} onClose={() => setCreated(null)} /> : null}
      </div>
    );
  }

  const root = (ReactDOM as any).createRoot(document.getElementById("root"));
  root.render(<App />);
})();
