/**
 * System Router — health, status, systemHealthCheck
 */

import { z } from 'zod';
import { join } from 'node:path';
import { access } from 'node:fs/promises';
import type { ProcedureBuilder } from '../trpc.js';
import { requireAccountRepository, requireProjectRepository } from './_helpers.js';
import { checkAccountHealth } from '../../agent/accounts/usage.js';
import { getProjectCloneDir } from '../../git/project-clones.js';

export const healthResponseSchema = z.object({
  status: z.literal('ok'),
  uptime: z.number().int().nonnegative(),
  processCount: z.number().int().nonnegative(),
});

export type HealthResponse = z.infer<typeof healthResponseSchema>;

export const processInfoSchema = z.object({
  id: z.string(),
  pid: z.number().int().positive(),
  command: z.string(),
  status: z.string(),
  startedAt: z.string(),
});

export type ProcessInfo = z.infer<typeof processInfoSchema>;

export const statusResponseSchema = z.object({
  server: z.object({
    startedAt: z.string(),
    uptime: z.number().int().nonnegative(),
    pid: z.number().int().positive(),
  }),
  processes: z.array(processInfoSchema),
});

export type StatusResponse = z.infer<typeof statusResponseSchema>;

export function systemProcedures(publicProcedure: ProcedureBuilder) {
  return {
    health: publicProcedure
      .output(healthResponseSchema)
      .query(({ ctx }): HealthResponse => {
        const uptime = ctx.serverStartedAt
          ? Math.floor((Date.now() - ctx.serverStartedAt.getTime()) / 1000)
          : 0;

        return {
          status: 'ok',
          uptime,
          processCount: ctx.processCount,
        };
      }),

    status: publicProcedure
      .output(statusResponseSchema)
      .query(({ ctx }): StatusResponse => {
        const uptime = ctx.serverStartedAt
          ? Math.floor((Date.now() - ctx.serverStartedAt.getTime()) / 1000)
          : 0;

        return {
          server: {
            startedAt: ctx.serverStartedAt?.toISOString() ?? '',
            uptime,
            pid: process.pid,
          },
          processes: [],
        };
      }),

    systemHealthCheck: publicProcedure
      .query(async ({ ctx }) => {
        const uptime = ctx.serverStartedAt
          ? Math.floor((Date.now() - ctx.serverStartedAt.getTime()) / 1000)
          : 0;

        const accountRepo = requireAccountRepository(ctx);
        const allAccounts = await accountRepo.findAll();
        const allAgents = ctx.agentManager ? await ctx.agentManager.list() : [];

        const accounts = await Promise.all(
          allAccounts.map(account => checkAccountHealth(account, allAgents, ctx.credentialManager, ctx.workspaceRoot ?? undefined))
        );

        const projectRepo = requireProjectRepository(ctx);
        const allProjects = await projectRepo.findAll();

        const projects = await Promise.all(
          allProjects.map(async project => {
            let repoExists = false;
            if (ctx.workspaceRoot) {
              const clonePath = join(ctx.workspaceRoot, getProjectCloneDir(project.name, project.id));
              try { await access(clonePath); repoExists = true; } catch { repoExists = false; }
            }
            return { id: project.id, name: project.name, url: project.url, repoExists };
          })
        );

        return {
          server: { status: 'ok' as const, uptime, startedAt: ctx.serverStartedAt?.toISOString() ?? null },
          accounts,
          projects,
        };
      }),
  };
}
