import { evaluateCustomerLifecycle } from '@pig/core';
import {
  accounts,
  activities,
  allocations,
  capacityRequests,
  contractObligations,
  contracts,
  demandDeals,
  type Database,
} from '@pig/db';
import { and, count, desc, eq, inArray } from 'drizzle-orm';
import { z } from 'zod';
import { resultScope } from './page-tools';
import { defineTool, type AgentTool } from './provider';

const noInput = z.object({}).strict();

/** The per-collection cap here, matching `RELATED_LIMIT` in chat-tools. */
const RELATED_LIMIT = 100;

export function createAccountLifecycleTool(db: Database, accountId: string): AgentTool {
  return defineTool({
    name: 'pig_get_account_lifecycle',
    description: 'Read the deterministic lifecycle score, source-backed signals, blockers, and sold or reserved capacity summary for the account in focus. Scores rank attention and are not probabilities or workload telemetry.',
    inputSchema: noInput,
    execute: async () => {
      const [account] = await db.select().from(accounts).where(eq(accounts.id, accountId)).limit(1);
      if (!account) throw new Error('The account in focus no longer exists.');
      const [deals, paperwork, recentActivity, dealsOnBook] = await Promise.all([
        db.select().from(demandDeals).where(eq(demandDeals.accountId, accountId)).limit(RELATED_LIMIT),
        db.select().from(contracts).where(and(eq(contracts.accountId, accountId), eq(contracts.side, 'demand'))).limit(RELATED_LIMIT),
        db.select().from(activities).where(eq(activities.accountId, accountId)).orderBy(desc(activities.occurredAt)).limit(1),
        // The denominator. This result is one account's slice of the book and
        // every count in it is an account count; without the book's own figure
        // beside them, "4 demand deals" is the only deal number in the payload
        // and becomes the answer to a question about the whole book.
        db.select({ value: count() }).from(demandDeals),
      ]);
      const demandDealsOnBook = dealsOnBook[0]?.value ?? 0;
      const dealIds = deals.map((deal) => deal.id);
      const contractIds = paperwork.map((contract) => contract.id);
      const [requests, reservations, obligations] = await Promise.all([
        dealIds.length ? db.select().from(capacityRequests).where(inArray(capacityRequests.demandDealId, dealIds)) : [],
        dealIds.length ? db.select().from(allocations).where(inArray(allocations.demandDealId, dealIds)) : [],
        contractIds.length ? db.select().from(contractObligations).where(inArray(contractObligations.contractId, contractIds)) : [],
      ]);
      return {
        scope: resultScope({
          covers: `belong to the account ${account.name}`,
          matched: deals.length,
          total: demandDealsOnBook,
          totalLabel: 'demand deal(s) on the book',
          listed: 0,
          filters: { accountId, side: 'demand', rowCapPerCollection: RELATED_LIMIT },
          truncated: deals.length >= RELATED_LIMIT || paperwork.length >= RELATED_LIMIT,
        }),
        account: { id: account.id, name: account.name },
        demandDealsForThisAccount: deals.length,
        demandDealsOnBook,
        lifecycle: evaluateCustomerLifecycle({
          accountId,
          deals: deals.map((deal) => ({ ...deal })),
          requests: requests.map((request) => ({ ...request, totalGpuHours: request.totalGpuHours == null ? null : Number(request.totalGpuHours) })),
          allocations: reservations.map((allocation) => ({ ...allocation, gpuHours: Number(allocation.gpuHours) })),
          contracts: paperwork,
          obligations,
          lastActivityAt: recentActivity[0]?.occurredAt ?? account.lastActivityAt,
          lastActivityId: recentActivity[0]?.id,
        }),
        interpretation: 'Scores rank review attention. Capacity totals mean sold or reserved capacity, not customer workload utilisation. Every figure here covers this one account, never the book.',
      };
    },
  });
}
