/**
 * ZCLAW UI Extensions Plugin
 * 
 * Registers custom Gateway RPC methods that the ZCLAW Tauri desktop UI
 * calls for features beyond standard OpenClaw protocol.
 * 
 * Custom methods:
 * - zclaw.clones.list     → list all agent clones (分身)
 * - zclaw.clones.create   → create a new clone
 * - zclaw.clones.update   → update clone config
 * - zclaw.clones.delete   → delete a clone
 * - zclaw.stats.usage     → token usage statistics
 * - zclaw.stats.sessions  → session statistics
 * - zclaw.config.quick    → quick configuration (name/role/scenarios)
 * - zclaw.workspace.info  → workspace information
 * - zclaw.plugins.status  → all ZCLAW plugin statuses
 */

import * as fs from 'fs';
import * as path from 'path';

interface PluginAPI {
  config: Record<string, any>;
  registerGatewayMethod(method: string, handler: (ctx: RpcContext) => void): void;
  registerHook(event: string, handler: (...args: any[]) => any, meta?: Record<string, any>): void;
}

interface RpcContext {
  params: Record<string, any>;
  respond(ok: boolean, payload: any): void;
}

// Clone (分身) management - stored in ZCLAW config
interface CloneConfig {
  id: string;
  name: string;
  role?: string;
  nickname?: string;
  scenarios?: string[];
  model?: string;
  createdAt: string;
}

export default function register(api: PluginAPI) {
  const configDir = process.env.OPENCLAW_HOME || path.join(process.env.HOME || process.env.USERPROFILE || '', '.openclaw');
  const zclawDataPath = path.join(configDir, 'zclaw-data.json');

  // Helper: read/write ZCLAW data
  function readZclawData(): { clones: CloneConfig[]; quickConfig?: Record<string, any> } {
    try {
      if (fs.existsSync(zclawDataPath)) {
        return JSON.parse(fs.readFileSync(zclawDataPath, 'utf-8'));
      }
    } catch { /* ignore */ }
    return { clones: [] };
  }

  function writeZclawData(data: any) {
    fs.mkdirSync(path.dirname(zclawDataPath), { recursive: true });
    fs.writeFileSync(zclawDataPath, JSON.stringify(data, null, 2), 'utf-8');
  }

  // === Clone Management ===

  api.registerGatewayMethod('zclaw.clones.list', ({ respond }: RpcContext) => {
    const data = readZclawData();
    respond(true, { clones: data.clones });
  });

  api.registerGatewayMethod('zclaw.clones.create', ({ params, respond }: RpcContext) => {
    const data = readZclawData();
    const clone: CloneConfig = {
      id: `clone_${Date.now().toString(36)}`,
      name: params.name || 'New Clone',
      role: params.role,
      nickname: params.nickname,
      scenarios: params.scenarios || [],
      model: params.model,
      createdAt: new Date().toISOString(),
    };
    data.clones.push(clone);
    writeZclawData(data);
    respond(true, { clone });
  });

  api.registerGatewayMethod('zclaw.clones.update', ({ params, respond }: RpcContext) => {
    const data = readZclawData();
    const index = data.clones.findIndex((c: CloneConfig) => c.id === params.id);
    if (index === -1) {
      respond(false, { error: 'Clone not found' });
      return;
    }
    data.clones[index] = { ...data.clones[index], ...params.updates };
    writeZclawData(data);
    respond(true, { clone: data.clones[index] });
  });

  api.registerGatewayMethod('zclaw.clones.delete', ({ params, respond }: RpcContext) => {
    const data = readZclawData();
    data.clones = data.clones.filter((c: CloneConfig) => c.id !== params.id);
    writeZclawData(data);
    respond(true, { ok: true });
  });

  // === Statistics ===

  api.registerGatewayMethod('zclaw.stats.usage', ({ respond }: RpcContext) => {
    // Read session files to compute token usage
    const sessionsDir = path.join(configDir, 'agents');
    const stats = {
      totalSessions: 0,
      totalMessages: 0,
      totalTokens: 0,
      byModel: {} as Record<string, { messages: number; inputTokens: number; outputTokens: number }>,
    };

    try {
      if (fs.existsSync(sessionsDir)) {
        const agentDirs = fs.readdirSync(sessionsDir);
        for (const agentDir of agentDirs) {
          const sessDir = path.join(sessionsDir, agentDir, 'sessions');
          if (!fs.existsSync(sessDir)) continue;
          const sessionFiles = fs.readdirSync(sessDir).filter((f: string) => f.endsWith('.jsonl'));
          stats.totalSessions += sessionFiles.length;

          for (const file of sessionFiles) {
            try {
              const content = fs.readFileSync(path.join(sessDir, file), 'utf-8');
              const lines = content.split('\n').filter(Boolean);
              for (const line of lines) {
                try {
                  const entry = JSON.parse(line);
                  if (entry.role === 'assistant' || entry.role === 'user') {
                    stats.totalMessages++;
                  }
                  if (entry.usage) {
                    const model = entry.model || 'unknown';
                    if (!stats.byModel[model]) {
                      stats.byModel[model] = { messages: 0, inputTokens: 0, outputTokens: 0 };
                    }
                    stats.byModel[model].messages++;
                    stats.byModel[model].inputTokens += entry.usage.input_tokens || 0;
                    stats.byModel[model].outputTokens += entry.usage.output_tokens || 0;
                    stats.totalTokens += (entry.usage.input_tokens || 0) + (entry.usage.output_tokens || 0);
                  }
                } catch { /* skip malformed lines */ }
              }
            } catch { /* skip unreadable files */ }
          }
        }
      }
    } catch { /* sessions dir may not exist yet */ }

    respond(true, stats);
  });

  api.registerGatewayMethod('zclaw.stats.sessions', ({ respond }: RpcContext) => {
    const sessionsDir = path.join(configDir, 'agents');
    const sessions: any[] = [];

    try {
      if (fs.existsSync(sessionsDir)) {
        const agentDirs = fs.readdirSync(sessionsDir);
        for (const agentDir of agentDirs) {
          const sessDir = path.join(sessionsDir, agentDir, 'sessions');
          if (!fs.existsSync(sessDir)) continue;
          const sessionFiles = fs.readdirSync(sessDir).filter((f: string) => f.endsWith('.jsonl'));
          for (const file of sessionFiles) {
            const stat = fs.statSync(path.join(sessDir, file));
            sessions.push({
              id: file.replace('.jsonl', ''),
              agentId: agentDir,
              createdAt: stat.birthtime.toISOString(),
              updatedAt: stat.mtime.toISOString(),
              size: stat.size,
            });
          }
        }
      }
    } catch { /* ignore */ }

    sessions.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
    respond(true, { sessions });
  });

  // === Quick Configuration ===

  api.registerGatewayMethod('zclaw.config.quick', ({ params, respond }: RpcContext) => {
    const data = readZclawData();
    if (params.get) {
      respond(true, { quickConfig: data.quickConfig || {} });
      return;
    }
    // Save quick config
    data.quickConfig = {
      userName: params.userName,
      userRole: params.userRole,
      agentNickname: params.agentNickname,
      scenarios: params.scenarios || [],
      workspaceDir: params.workspaceDir,
    };
    writeZclawData(data);
    respond(true, { ok: true, quickConfig: data.quickConfig });
  });

  // === Workspace Info ===

  api.registerGatewayMethod('zclaw.workspace.info', ({ respond }: RpcContext) => {
    const workspace = api.config?.agents?.defaults?.workspace || '~/.openclaw/zclaw-workspace';
    const resolvedPath = workspace.replace('~', process.env.HOME || process.env.USERPROFILE || '');
    
    let exists = false;
    let fileCount = 0;
    let totalSize = 0;

    try {
      exists = fs.existsSync(resolvedPath);
      if (exists) {
        const files = fs.readdirSync(resolvedPath, { recursive: true }) as string[];
        for (const file of files) {
          const fullPath = path.join(resolvedPath, file);
          try {
            const stat = fs.statSync(fullPath);
            if (stat.isFile()) {
              fileCount++;
              totalSize += stat.size;
            }
          } catch { /* skip */ }
        }
      }
    } catch { /* ignore */ }

    respond(true, {
      path: workspace,
      resolvedPath,
      exists,
      fileCount,
      totalSize,
    });
  });

  // === Plugin Status ===

  api.registerGatewayMethod('zclaw.plugins.status', ({ respond }: RpcContext) => {
    respond(true, {
      plugins: [
        { id: 'zclaw-chinese-models', status: 'active', version: '0.1.0' },
        { id: 'zclaw-feishu', status: api.config?.channels?.feishu?.enabled ? 'active' : 'inactive', version: '0.1.0' },
        { id: 'zclaw-ui', status: 'active', version: '0.1.0' },
      ],
    });
  });

  // Startup log
  api.registerHook('gateway:startup', async () => {
    console.log('[ZCLAW] UI extension RPC methods registered');
  }, { name: 'zclaw-ui.startup', description: 'Log ZCLAW UI extensions registration' });
}
