import { z } from 'zod';
import { ProbeStatusSchema } from '../hermes-ops/types.js';

// Hermes telemetry snapshot — read-only "real artifacts" per Phase 3 Decision #1
// (sessions, cron, memory, skills, watchdog alerts, backup history).
// Each section carries its own `ProbeStatus` so the UI can distinguish
// "definitely empty" from "couldn't read the source" (CLI missing, permission
// denied, timed out). Mirrors the hermes-ops shape: every field set the UI
// renders has a status it can surface.

export const HermesInstanceIdSchema = z.enum(['vijay', 'bheem']);
export type HermesInstanceId = z.infer<typeof HermesInstanceIdSchema>;

export const HermesSessionStatsSchema = z.object({
  totalSessions: z.number(),
  totalMessages: z.number(),
  status: ProbeStatusSchema,
});
export type HermesSessionStats = z.infer<typeof HermesSessionStatsSchema>;

export const HermesSessionEntrySchema = z.object({
  id: z.string(),
  sessionKey: z.string(),
  platform: z.string().nullable(),
  chatType: z.string().nullable(),
  displayName: z.string().nullable(),
  createdAt: z.string().nullable(),
  updatedAt: z.string().nullable(),
  suspended: z.boolean(),
  resumePending: z.boolean(),
  totalTokens: z.number().nullable(),
  estimatedCostUsd: z.number().nullable(),
});
export type HermesSessionEntry = z.infer<typeof HermesSessionEntrySchema>;

export const HermesSessionListSchema = z.object({
  entries: z.array(HermesSessionEntrySchema),
  status: ProbeStatusSchema,
});
export type HermesSessionList = z.infer<typeof HermesSessionListSchema>;

export const HermesSessionEventSchema = z.object({
  id: z.string(),
  sessionFile: z.string(),
  timestamp: z.string().nullable(),
  role: z.string().nullable(),
  eventType: z.enum(['message', 'tool-call', 'tool-result', 'reasoning', 'system', 'unknown']),
  summary: z.string(),
  toolNames: z.array(z.string()),
  itemTypes: z.array(z.string()),
  status: z.string().nullable(),
});
export type HermesSessionEvent = z.infer<typeof HermesSessionEventSchema>;

export const HermesSessionEventListSchema = z.object({
  entries: z.array(HermesSessionEventSchema),
  status: ProbeStatusSchema,
  sourceCount: z.number(),
});
export type HermesSessionEventList = z.infer<typeof HermesSessionEventListSchema>;

export const HermesCronEntrySchema = z.object({
  id: z.string(),
  name: z.string(),
  schedule: z.string().nullable(),
  lastRun: z.string().nullable(),
  nextRun: z.string().nullable(),
  lastStatus: z.string().nullable(),
  active: z.boolean(),
});
export type HermesCronEntry = z.infer<typeof HermesCronEntrySchema>;

export const HermesCronListSchema = z.object({
  entries: z.array(HermesCronEntrySchema),
  status: ProbeStatusSchema,
});
export type HermesCronList = z.infer<typeof HermesCronListSchema>;

export const HermesMemoryItemSchema = z.object({
  id: z.string(),
  type: z.string(),
  key: z.string(),
  summary: z.string(),
  updatedAt: z.string().nullable(),
});
export type HermesMemoryItem = z.infer<typeof HermesMemoryItemSchema>;

export const HermesMemoryListSchema = z.object({
  items: z.array(HermesMemoryItemSchema),
  status: ProbeStatusSchema,
});
export type HermesMemoryList = z.infer<typeof HermesMemoryListSchema>;

export const HermesSkillItemSchema = z.object({
  id: z.string(),
  name: z.string(),
  description: z.string(),
  enabled: z.boolean(),
});
export type HermesSkillItem = z.infer<typeof HermesSkillItemSchema>;

export const HermesSkillListSchema = z.object({
  items: z.array(HermesSkillItemSchema),
  status: ProbeStatusSchema,
});
export type HermesSkillList = z.infer<typeof HermesSkillListSchema>;

// Severity is a union of `info | warn | critical` so the UI can colour-code.
// Watchdog scripts emit "WARNING" / "CRITICAL" prefixes today; we normalize.
export const HermesWatchdogSeveritySchema = z.enum(['info', 'warn', 'critical']);
export type HermesWatchdogSeverity = z.infer<typeof HermesWatchdogSeveritySchema>;

export const HermesWatchdogAlertSchema = z.object({
  timestamp: z.string(),
  severity: HermesWatchdogSeveritySchema,
  message: z.string(),
});
export type HermesWatchdogAlert = z.infer<typeof HermesWatchdogAlertSchema>;

export const HermesWatchdogFeedSchema = z.object({
  alerts: z.array(HermesWatchdogAlertSchema),
  // Path the alerts were read from (or where they would be read from when
  // the source becomes available). Null when no canonical path is known.
  source: z.string().nullable(),
  status: ProbeStatusSchema,
});
export type HermesWatchdogFeed = z.infer<typeof HermesWatchdogFeedSchema>;

export const HermesBackupHistoryEntrySchema = z.object({
  sha: z.string(),
  committedAt: z.string(),
  subject: z.string(),
});
export type HermesBackupHistoryEntry = z.infer<typeof HermesBackupHistoryEntrySchema>;

export const HermesBackupHistorySchema = z.object({
  entries: z.array(HermesBackupHistoryEntrySchema),
  // Repo path probed (informational; useful when status is `unknown`).
  repoPath: z.string().nullable(),
  status: ProbeStatusSchema,
});
export type HermesBackupHistory = z.infer<typeof HermesBackupHistorySchema>;

export const HermesTokenSummarySchema = z.object({
  sessionCount: z.number(),
  messageCount: z.number(),
  toolCallCount: z.number(),
  inputTokens: z.number(),
  outputTokens: z.number(),
  cacheReadTokens: z.number(),
  cacheWriteTokens: z.number(),
  reasoningTokens: z.number(),
  totalTokens: z.number(),
  estimatedCostUsd: z.number(),
  actualCostUsd: z.number(),
  firstStartedAt: z.string().nullable(),
  lastActivityAt: z.string().nullable(),
});
export type HermesTokenSummary = z.infer<typeof HermesTokenSummarySchema>;

export const HermesTokenByModelSchema = z.object({
  model: z.string(),
  provider: z.string(),
  sessionCount: z.number(),
  totalTokens: z.number(),
  estimatedCostUsd: z.number(),
});
export type HermesTokenByModel = z.infer<typeof HermesTokenByModelSchema>;

export const HermesTokenByDaySchema = z.object({
  day: z.string(),
  sessionCount: z.number(),
  totalTokens: z.number(),
  estimatedCostUsd: z.number(),
});
export type HermesTokenByDay = z.infer<typeof HermesTokenByDaySchema>;

export const HermesTokenSessionSchema = z.object({
  id: z.string(),
  title: z.string().nullable(),
  source: z.string().nullable(),
  model: z.string(),
  provider: z.string(),
  startedAt: z.string().nullable(),
  endedAt: z.string().nullable(),
  totalTokens: z.number(),
  messageCount: z.number(),
  toolCallCount: z.number(),
  estimatedCostUsd: z.number(),
});
export type HermesTokenSession = z.infer<typeof HermesTokenSessionSchema>;

export const HermesTokenUsageSnapshotSchema = z.object({
  generatedAt: z.string(),
  cached: z.boolean(),
  instanceId: HermesInstanceIdSchema,
  status: ProbeStatusSchema,
  source: z.string().nullable(),
  summary: HermesTokenSummarySchema,
  byModel: z.array(HermesTokenByModelSchema),
  byDay: z.array(HermesTokenByDaySchema),
  recentSessions: z.array(HermesTokenSessionSchema),
  warnings: z.array(z.string()),
});
export type HermesTokenUsageSnapshot = z.infer<typeof HermesTokenUsageSnapshotSchema>;

export const HermesTelemetrySnapshotSchema = z.object({
  generatedAt: z.string(),
  // True when this payload was served from the short-TTL cache.
  cached: z.boolean(),
  instanceId: HermesInstanceIdSchema,
  sessions: HermesSessionStatsSchema,
  sessionList: HermesSessionListSchema,
  sessionEvents: HermesSessionEventListSchema,
  cron: HermesCronListSchema,
  memory: HermesMemoryListSchema,
  skills: HermesSkillListSchema,
  watchdog: HermesWatchdogFeedSchema,
  backupHistory: HermesBackupHistorySchema,
  // Roll-up of any "couldn't tell" / probe-failed conditions; the UI renders
  // these inline without changing the structural shape of the snapshot.
  warnings: z.array(z.string()),
});
export type HermesTelemetrySnapshot = z.infer<typeof HermesTelemetrySnapshotSchema>;
