/**
 * SocialFastCoordinatorAgent — A2A pipeline for NomGap group fast coordination.
 *
 * Agent roster (3 steps):
 *   1. GroupMemberResolverAgent  — given a fasting session, identify the group member user IDs
 *   2. NotificationDispatchAgent — fire social_invite push to all members; fire stage milestone pushes
 *   3. CoordinationReportAgent  — assemble per-member notification results + weekly_digest summary
 *
 * MCP tools:
 *   nomgap.social.coordinateFast(sessionId, memberUserIds) — run pipeline for a group fast
 */

import { randomUUID } from 'node:crypto';
import { z } from 'zod';
import { registerTool } from '../tools/registry.js';
import type { McpToolRequest } from '../tools/types.js';
import {
  nomgapFastingSessionGet,
  nomgapPushFire,
  type FastingSessionDoc,
} from '../../lib/nomgap-client.js';

// ── Types ──────────────────────────────────────────────────────────────────────

type PushOutcome = 'fired' | 'failed';

interface MemberNotification {
  userId: string;
  type: string;
  outcome: PushOutcome;
  error?: string;
}

export interface SocialFastCoordinationReport {
  runId: string;
  productId: 'nomgap';
  sessionId: string;
  protocolId: string | null;
  currentStage: string | null;
  memberCount: number;
  notificationsFired: number;
  notificationsFailed: number;
  perMember: MemberNotification[];
  weeklyDigestFired: boolean;
  summary: string;
  generatedAt: string;
}

// ── Step 1: GroupMemberResolverAgent ──────────────────────────────────────────

async function resolveSession(
  sessionId: string,
  opts: { token?: string; requestId?: string }
): Promise<FastingSessionDoc | null> {
  try {
    return await nomgapFastingSessionGet(sessionId, opts);
  } catch {
    return null;
  }
}

// ── Step 2: NotificationDispatchAgent ─────────────────────────────────────────

async function notifyMembers(
  sessionId: string,
  session: FastingSessionDoc | null,
  memberUserIds: string[],
  opts: { token?: string; requestId?: string }
): Promise<MemberNotification[]> {
  const results: MemberNotification[] = [];

  for (const userId of memberUserIds) {
    // Fire social_invite to each member
    try {
      await nomgapPushFire({ type: 'social_invite', userId }, opts);
      results.push({ userId, type: 'social_invite', outcome: 'fired' });
    } catch (err) {
      results.push({
        userId,
        type: 'social_invite',
        outcome: 'failed',
        error: err instanceof Error ? err.message : String(err),
      });
    }

    // If session has stage entries (fast is progressing), fire stage_transition milestone push
    const hasStages =
      session !== null && Array.isArray(session.stages) && session.stages.length > 0;
    if (hasStages) {
      try {
        await nomgapPushFire({ type: 'stage_transition', userId }, opts);
        results.push({ userId, type: 'stage_transition', outcome: 'fired' });
      } catch (err) {
        results.push({
          userId,
          type: 'stage_transition',
          outcome: 'failed',
          error: err instanceof Error ? err.message : String(err),
        });
      }
    }
  }

  return results;
}

// ── Step 3: CoordinationReportAgent ──────────────────────────────────────────

async function sendWeeklyDigestAndReport(
  runId: string,
  sessionId: string,
  session: FastingSessionDoc | null,
  memberUserIds: string[],
  notifications: MemberNotification[],
  opts: { token?: string; requestId?: string }
): Promise<SocialFastCoordinationReport> {
  // Send weekly_digest to the session owner as summary
  let weeklyDigestFired = false;
  const ownerId = session?.userId;
  if (ownerId) {
    try {
      await nomgapPushFire({ type: 'weekly_digest', userId: ownerId }, opts);
      weeklyDigestFired = true;
    } catch {
      // best-effort
    }
  }

  const fired = notifications.filter(n => n.outcome === 'fired').length;
  const failed = notifications.filter(n => n.outcome === 'failed').length;
  const stage =
    session && Array.isArray(session.stages) && session.stages.length > 0
      ? `stage_${session.stages.length}`
      : null;
  const protocolId = session?.protocolId ?? null;

  const summary =
    memberUserIds.length === 0
      ? 'No group members specified — no notifications dispatched.'
      : `Coordinated group fast session ${sessionId} for ${memberUserIds.length} member(s). ${fired} notification(s) fired, ${failed} failed. Weekly digest to owner: ${weeklyDigestFired ? 'sent' : 'skipped'}.`;

  return {
    runId,
    productId: 'nomgap',
    sessionId,
    protocolId,
    currentStage: stage,
    memberCount: memberUserIds.length,
    notificationsFired: fired,
    notificationsFailed: failed,
    perMember: notifications,
    weeklyDigestFired,
    summary,
    generatedAt: new Date().toISOString(),
  };
}

// ── Pipeline runner ────────────────────────────────────────────────────────────

async function runSocialFastCoordinatorPipeline(
  sessionId: string,
  memberUserIds: string[],
  req: McpToolRequest
): Promise<SocialFastCoordinationReport> {
  const runId = randomUUID();
  const opts = { token: req.headers.authorization?.slice(7), requestId: req.id };

  req.log.info({ runId, stepId: 'resolve', sessionId }, 'GroupMemberResolverAgent start');
  const session = await resolveSession(sessionId, opts);
  req.log.info(
    { runId, stepId: 'resolve', found: session !== null },
    'GroupMemberResolverAgent done'
  );

  req.log.info(
    { runId, stepId: 'dispatch', memberCount: memberUserIds.length },
    'NotificationDispatchAgent start'
  );
  const notifications = await notifyMembers(sessionId, session, memberUserIds, opts);
  req.log.info(
    { runId, stepId: 'dispatch', fired: notifications.filter(n => n.outcome === 'fired').length },
    'NotificationDispatchAgent done'
  );

  req.log.info({ runId, stepId: 'report' }, 'CoordinationReportAgent start');
  const report = await sendWeeklyDigestAndReport(
    runId,
    sessionId,
    session,
    memberUserIds,
    notifications,
    opts
  );
  req.log.info(
    { runId, stepId: 'report', summary: report.summary },
    'CoordinationReportAgent done'
  );

  return report;
}

// ── MCP tool registration ─────────────────────────────────────────────────────

registerTool({
  name: 'nomgap.social.coordinateFast',
  description:
    'A2A pipeline: coordinates a NomGap group fast by resolving the session, firing social_invite and stage_transition push notifications to all group members, and sending a weekly_digest summary to the session owner. Use when a new group fast is created or when members need to be re-notified. Requires admin role.',
  requiredRole: 'admin',
  inputSchema: z.object({
    sessionId: z.string().min(1).describe('Fasting session ID for the group fast'),
    memberUserIds: z
      .array(z.string().min(1))
      .min(1)
      .describe('List of user IDs to notify as group fast members'),
  }),
  async execute(args, req) {
    return runSocialFastCoordinatorPipeline(args.sessionId, args.memberUserIds, req);
  },
});
