import os from 'os';
import { statfsSync } from 'fs';
import type { Tool, ToolResult } from '../types.js';

function formatUptime(seconds: number): string {
  const days = Math.floor(seconds / 86400);
  const hours = Math.floor((seconds % 86400) / 3600);
  const minutes = Math.floor((seconds % 3600) / 60);
  return `${days}d ${hours}h ${minutes}m`;
}

function formatBytes(bytes: number): string {
  return (bytes / (1024 * 1024 * 1024)).toFixed(2) + ' GB';
}

function getDiskUsageSummary(): { lines: string[]; usedPct?: number } {
  try {
    const rootPath = process.platform === 'win32' ? process.cwd().slice(0, 3) : '/';
    const stat = statfsSync(rootPath);
    const blockSize = typeof stat.bsize === 'number' ? stat.bsize : Number(stat.bsize);
    const totalBlocks = typeof stat.blocks === 'number' ? stat.blocks : Number(stat.blocks);
    const freeBlocks = typeof stat.bavail === 'number' ? stat.bavail : Number(stat.bavail);

    if (!Number.isFinite(blockSize) || !Number.isFinite(totalBlocks) || !Number.isFinite(freeBlocks)) {
      return {
        lines: [
          'Storage',
          '- Root Path: unavailable',
          '- Total: unavailable',
          '- Free: unavailable',
          '- Used: unavailable',
        ],
      };
    }

    const totalBytes = totalBlocks * blockSize;
    const freeBytes = freeBlocks * blockSize;
    const usedBytes = Math.max(0, totalBytes - freeBytes);
    const usedPct = totalBytes > 0 ? (usedBytes / totalBytes) * 100 : 0;

    return {
      lines: [
        'Storage',
        `- Root Path: ${rootPath}`,
        `- Total: ${formatBytes(totalBytes)}`,
        `- Free: ${formatBytes(freeBytes)}`,
        `- Used: ${formatBytes(usedBytes)} (${usedPct.toFixed(1)}%)`,
      ],
      usedPct,
    };
  } catch {
    return {
      lines: [
        'Storage',
        '- Root Path: unavailable',
        '- Total: unavailable',
        '- Free: unavailable',
        '- Used: unavailable',
      ],
    };
  }
}

export const systemInfoTool: Tool = {
  name: 'system.info',
  description: 'Get current system information including date, time, hostname, OS, platform, architecture, uptime, Node.js version, and memory usage.',
  inputSchema: {
    type: 'object',
    properties: {},
    required: [],
  },
  execute: async (_rawArgs: unknown): Promise<ToolResult> => {
    try {
      const now = new Date();
      const dateStr = now.toLocaleDateString('en-US', {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric',
      });
      const timeStr = now.toLocaleTimeString('en-US', {
        hour: '2-digit',
        minute: '2-digit',
        timeZoneName: 'short',
        hour12: false,
      });
      const isoStr = now.toISOString();
      const localStr = now.toLocaleString();

      const totalMem = os.totalmem();
      const freeMem = os.freemem();
      const usedMem = Math.max(0, totalMem - freeMem);
      const usedMemPct = totalMem > 0 ? (usedMem / totalMem) * 100 : 0;
      const disk = getDiskUsageSummary();
      const memoryHealth = usedMemPct < 75 ? 'healthy' : usedMemPct < 90 ? 'moderate' : 'high';
      const diskHealth = typeof disk.usedPct === 'number'
        ? (disk.usedPct < 75 ? 'healthy' : disk.usedPct < 90 ? 'moderate' : 'high')
        : 'unknown';

      const lines = [
        'System Snapshot',
        '',
        'Host',
        `- Hostname: ${os.hostname()}`,
        `- OS: ${os.type()} ${os.release()}`,
        `- Platform: ${os.platform()} (${os.arch()})`,
        `- Node.js: ${process.version}`,
        `- Uptime: ${formatUptime(os.uptime())}`,
        '',
        'Resources',
        `- Memory: ${formatBytes(usedMem)} used / ${formatBytes(totalMem)} total (${usedMemPct.toFixed(1)}% used, ${memoryHealth})`,
        `- Memory Free: ${formatBytes(freeMem)}`,
        ...disk.lines.map((line) => (line === 'Storage' ? line : `${line}`)),
        '',
        'Time',
        `- Local: ${localStr}`,
        `- Date: ${dateStr}`,
        `- Time: ${timeStr}`,
        `- ISO 8601: ${isoStr}`,
        '',
        'Process',
        `- Working Dir: ${process.cwd()}`,
        `- Health Summary: memory=${memoryHealth}, disk=${diskHealth}`,
      ];

      return { success: true, output: lines.join('\n') };
    } catch (error) {
      return { success: false, output: '', error: error instanceof Error ? error.message : String(error) };
    }
  },
};
