// Типы ответа бэкенда + мелкие помощники форматирования.
// Файлы фронтенда не модули (сборки нет), поэтому обмен идёт через window.

type OwnerSide = "OUR_TEAM" | "CUSTOMER" | "UNKNOWN";

interface Person { name: string; role: string }
interface ExistingTask { id: string; title: string; description: string }

interface SuggestedUpdates {
  description_addition: string | null;
  deadline: string | null;
  priority: string | null;
  context_note: string | null;
}

interface ActionItem {
  id: string;
  title: string;
  description: string;
  assignee?: string | null;
  owner?: string | null;
  owner_side: OwnerSide;
  deadline: string | null;
  deadline_text: string | null;
  priority?: string;
  confidence: number;
  source_quote: string;
  quote_verified: boolean;
  why_unclear?: string;
  warnings: string[];
}

interface Duplicate {
  new_task_title: string;
  existing_task_id: string;
  existing_task_title: string;
  similarity_score: number;
  reason: string;
  level: "likely" | "related";
  suggested_updates: SuggestedUpdates;
}

interface AnalysisResult {
  meeting_summary: string;
  our_tasks: ActionItem[];
  customer_commitments: ActionItem[];
  unclear_actions: ActionItem[];
  decisions: { text: string; source_quote: string; quote_verified: boolean }[];
  open_questions: { text: string; source_quote: string; quote_verified: boolean }[];
  potential_duplicates: Duplicate[];
}

interface AnalyzeResponse {
  result: AnalysisResult;
  provider: string;
  model: string;
  meeting_type: string;
  meeting_date: string;
  validation_warnings: string[];
  elapsed_ms: number;
}

const MONTHS_RU = ["января", "февраля", "марта", "апреля", "мая", "июня",
  "июля", "августа", "сентября", "октября", "ноября", "декабря"];

function formatDeadline(item: { deadline: string | null; deadline_text: string | null }): string {
  if (item.deadline) {
    const parts = item.deadline.split("-");
    if (parts.length === 3) {
      const m = parseInt(parts[1], 10) - 1;
      return parseInt(parts[2], 10) + " " + (MONTHS_RU[m] || parts[1]);
    }
    return item.deadline;
  }
  if (item.deadline_text) return item.deadline_text;
  return "не указан";
}

const PRIORITY_LABEL: Record<string, string> = {
  low: "низкий", medium: "средний", high: "высокий", unknown: "не указан",
};

const OWNER_LABEL: Record<string, string> = {
  OUR_TEAM: "наша команда", CUSTOMER: "заказчик", UNKNOWN: "не определено",
};

function confidenceTone(c: number): { bar: string; text: string } {
  if (c >= 0.85) return { bar: "bg-lime-deep", text: "text-ink" };
  if (c >= 0.6) return { bar: "bg-amber-400", text: "text-ink-soft" };
  return { bar: "bg-rose-400", text: "text-ink-soft" };
}

const pct = (x: number) => Math.round((x || 0) * 100) + "%";

function plural(count: number, one: string, few: string, many: string): string {
  const tail = Math.abs(count) % 100;
  if (tail >= 11 && tail <= 14) return many;
  const last = tail % 10;
  if (last === 1) return one;
  if (last >= 2 && last <= 4) return few;
  return many;
}

// имя файла расшифровки — это не название встречи: убираем дату, время, метки и расширение
function cleanTitle(raw: string): string {
  let text = (raw || "").trim();
  text = text.replace(/\.(txt|md|vtt|srt|docx?)$/i, "");
  text = text.replace(/[_]+/g, " ");
  text = text.replace(/^\s*\d{4}[-. ]\d{2}[-. ]\d{2}\s*/, "");
  text = text.replace(/^\s*\d{3,4}\s*/, "");
  text = text.replace(/^\s*\((?:MSK|UTC|GMT)[^)]*\)\s*/i, "");
  text = text.replace(/^\s*\[[^\]]{1,12}\]\s*/, "");
  text = text.replace(/^\s*(?:[A-Z]{2,5}\s+)+/, "");
  text = text.replace(/\s+/g, " ").trim();
  return text || (raw || "Встреча");
}

function initDataFromUrl(): string {
  // Telegram кладёт подпись во фрагмент адреса — это работает даже если SDK не успел загрузиться
  try {
    const hash = (window.location.hash || "").replace(/^#/, "");
    if (hash) {
      const value = new URLSearchParams(hash).get("tgWebAppData");
      if (value) return value;
    }
    return new URLSearchParams(window.location.search).get("tgWebAppData") || "";
  } catch (e) {
    return "";
  }
}

function authHeaders(): Record<string, string> {
  // внутри Telegram страница подписывает свои запросы, снаружи заголовка просто нет
  const tg = (window as any).Telegram && (window as any).Telegram.WebApp;
  const initData = (tg && tg.initData) || initDataFromUrl();
  return initData ? { "X-Telegram-Init-Data": initData } : {};
}

async function postJSON(url: string, body: any): Promise<any> {
  const r = await fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json", ...authHeaders() },
    body: JSON.stringify(body),
  });
  const data = await r.json().catch(() => ({}));
  if (!r.ok) throw new Error((data && data.detail) || ("Ошибка " + r.status));
  return data;
}

async function getJSON(url: string): Promise<any> {
  const r = await fetch(url, { headers: authHeaders() });
  if (!r.ok) {
    const data = await r.json().catch(() => ({}));
    throw new Error((data && data.detail) || ("Ошибка " + r.status));
  }
  return r.json();
}

(window as any).AppTypes = {
  authHeaders, cleanTitle, plural, formatDeadline, PRIORITY_LABEL, OWNER_LABEL, confidenceTone, pct, postJSON, getJSON,
};
