/**
 * Which read tool answers which page.
 *
 * Two callers need this mapping and they must not drift: `page-tools.ts` uses
 * it to decide what to hand the model, and `chat.ts` uses it to name the tool
 * in the system prompt. A model told "you are on /margin" without being told
 * which tool reads the margin book tends to guess at figures instead of
 * calling anything.
 *
 * Deliberately free of database imports so the prompt module does not pull
 * @pig/db in behind it.
 */
import type { PiggyPageRoute } from '@pig/core';

/**
 * Every tool a page may be given. Each name starts `pig_` because
 * `assertPigToolBoundary` refuses the request otherwise, before inference.
 */
export const PIGGY_PAGE_TOOL_NAMES = [
  'pig_get_workspace_summary',
  'pig_get_margin_summary',
  'pig_get_idle_capacity',
  'pig_get_pipeline',
  'pig_get_calendar_ahead',
  'pig_get_motion_summary',
  'pig_search_motion_library',
  'pig_get_engagement',
] as const;

export type PiggyPageToolName = (typeof PIGGY_PAGE_TOOL_NAMES)[number];

export interface PiggyPageGuide {
  /** How the page is named to the model. */
  label: string;
  /** The one tool that grounds an answer about this page. */
  tool: PiggyPageToolName;
}

/**
 * Partial rather than exhaustive: a route added to `PIGGY_PAGE_ROUTES` in
 * @pig/core should fall back to the workspace summary, not fail to compile.
 * The dock publishes a route on every navigation, and a page that cannot be
 * navigated to is worse than a page Piggy knows less about.
 *
 * The label is not decoration. `chat.ts` renders it as "the user is looking at
 * LABEL — call TOOL before making any claim about what is on it", so a label
 * that promises more than its tool reads is an instruction to answer confidently
 * from the wrong payload. Where the tool sees only part of the page — every
 * route that falls through to the workspace summary, and /contracts — the label
 * says which part, because the alternative is the model inventing the rest.
 */
const GUIDES: Partial<Record<PiggyPageRoute, PiggyPageGuide>> = {
  '/': { label: 'the Overview dashboard', tool: 'pig_get_workspace_summary' },
  /*
   * Growth used to name the pipeline tool, which returns stage counts and deal
   * values — neither of which appears anywhere on that page. Its own figures
   * are the idle ones: the "Idle supply cost" stat and the idle tab are
   * `CapacityService.idleCapacity({ thresholdPct: 0.25, withinDays: 30 })`,
   * which is exactly what `pig_get_idle_capacity` reports, down to the
   * defaults. The lifecycle scores beside them belong to an account, and the
   * Ask Piggy button on each card already carries that account as a record
   * context, so the page-level tool covers what those buttons cannot.
   */
  '/growth': {
    label: 'the growth view — attention-ranked accounts, and the idle supply behind them',
    tool: 'pig_get_idle_capacity',
  },
  /*
   * "Commitment by commitment" was a promise the tool does not keep: it returns
   * book totals and the eight largest blocks by cost, so a question about the
   * ninth is answered from a list that does not contain it.
   */
  '/margin': {
    label: 'the margin report — book totals, and the largest commitments by cost',
    tool: 'pig_get_margin_summary',
  },
  /*
   * A window, not the calendar. `pig_get_calendar_ahead` projects the next 30
   * days by default and what has lapsed in the last 90; anything dated outside
   * that is not in the payload at all, and "the calendar of dated work" invited
   * the model to report the window as the whole of it.
   */
  '/calendar': {
    label: 'the calendar of dated work — Piggy reads a window of it, not the whole calendar',
    tool: 'pig_get_calendar_ahead',
  },
  /*
   * The tool lists only the blocks that are at least 25% unsold. It carries the
   * size of the book beside them now, so the count is safe, but the rows are
   * still the idle ones and the label should not promise the book.
   */
  '/capacity': {
    label: 'the capacity book — Piggy reads the idle blocks and how many commitments are live',
    tool: 'pig_get_idle_capacity',
  },
  '/demand': { label: 'the demand pipeline board', tool: 'pig_get_pipeline' },
  '/supply': { label: 'the supply pipeline board', tool: 'pig_get_pipeline' },
  /*
   * This label used to say Piggy could not read accounts at all, which was true
   * of the tool and produced the defect anyway. Measured in production: asked
   * "How many accounts are on the book in total?" here, Piggy answered "The book
   * contains 7 demand deals (accounts) in total" — the book held 17 accounts and
   * 7 demand deals. A label admitting a gap does not stop a model filling it; it
   * only tells the model which gap to fill. So the summary now counts accounts
   * and contacts, and the label promises exactly that and no more: the counts
   * are there, the rows are not, and `pig_search_records` is how a row is found.
   */
  '/accounts': {
    label:
      'the accounts list — Piggy reads how many accounts (by side) and contacts are on the ' +
      'book, not the rows themselves',
    tool: 'pig_get_workspace_summary',
  },
  /*
   * The calendar, and deliberately so, which reads like a mistake until you
   * look at what it projects: contract effective, executed and expiry dates,
   * renewal notices and obligations due are all built FROM `contracts` and
   * `contract_obligations` (apps/api/src/services/calendar.ts). It is the only
   * page tool that touches the contracts table at all — the workspace summary
   * knows nothing but commitments and deals — so pointing this route anywhere
   * else leaves Piggy with no contract data whatsoever.
   *
   * What was wrong was the promise. Told it was looking at "the contracts list"
   * and handed a thirty-day projection, the model has nothing to stop it
   * reporting that window as the whole book — the paper with no date inside the
   * horizon simply is not in the payload. The label now scopes the claim to the
   * dated half, which is the half the tool can defend. A real contract-book
   * tool would be better, and would belong in page-tools.ts.
   */
  '/contracts': {
    label: 'the contracts list — Piggy reads its dates here, not its terms',
    tool: 'pig_get_calendar_ahead',
  },
  '/motion': {
    label: 'the Motion home — stage coverage, the shared library, and recent promotions',
    tool: 'pig_get_motion_summary',
  },
  /*
   * The label says "shared" because the tool reads nothing else, and the model
   * is otherwise free to conclude that a template it cannot find is missing
   * rather than private. A user asking "where is my draft?" should be told
   * Piggy cannot see private drafts, not that no such template exists.
   */
  '/motion/library': {
    label: 'the motion library — Piggy reads the shared templates here, never a private draft',
    tool: 'pig_search_motion_library',
  },
  '/motion/engagements': {
    label: 'the engagement list — the demand deals with a motion running against them',
    tool: 'pig_get_engagement',
  },
  /*
   * Four pages with no data tool of their own, and the four labels that were
   * most dangerous: each named a subject — imports, the team, the fact queue,
   * the settings — while handing the model book totals about something else
   * entirely. That is precisely the shape that produced the /accounts answer,
   * where a figure about deals was relabelled as a figure about accounts, and
   * here there is no figure to add: nothing in the workspace summary counts an
   * import run, a person, a pending fact or a setting.
   *
   * So each label states the refusal rather than the subject. "I cannot see that
   * from here" is an answer the grounding rule already sanctions; what it needed
   * was something specific enough to recognise the question by.
   */
  '/imports': {
    label:
      'the CSV import page — Piggy can see book totals only, and nothing about import runs, ' +
      'column mappings or file contents',
    tool: 'pig_get_workspace_summary',
  },
  '/team': {
    label:
      'the team and permissions page — Piggy can see book totals only, and no users, roles, ' +
      'invitations or permissions at all',
    tool: 'pig_get_workspace_summary',
  },
  '/facts': {
    label:
      'the fact review queue — Piggy can see book totals only, and no facts and no count of ' +
      'what is pending review',
    tool: 'pig_get_workspace_summary',
  },
  '/settings': {
    label:
      'the settings page — Piggy can see book totals only, and no settings, integrations, ' +
      'API keys or connected accounts',
    tool: 'pig_get_workspace_summary',
  },
  /*
   * The one route whose label promises nothing about a page, because there is no
   * page behind it: the full-page chat is wherever the conversation goes. The
   * summary is the widest tool available, so naming what it covers is the only
   * useful thing to say here.
   */
  '/piggy': {
    label: 'the full-page Piggy chat, with the book-level workspace summary behind it',
    tool: 'pig_get_workspace_summary',
  },
};

/**
 * The fallback carries the same warning the four data-less pages carry.
 *
 * A route in `PIGGY_PAGE_ROUTES` with no entry above — /learn today, and every
 * page added later — was described to the model as "the /learn page" and handed
 * the workspace summary, which is the /accounts failure with a different noun.
 * A generic label cannot say what the page holds, but it can say what the tool
 * does not, and that is the half that stops an answer being invented.
 */
export function piggyPageGuide(route: PiggyPageRoute): PiggyPageGuide {
  return (
    GUIDES[route] ?? {
      label: `the ${route} page — Piggy can see book totals only, and nothing that is on this page`,
      tool: 'pig_get_workspace_summary',
    }
  );
}
