import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Param,
  Body,
  NotFoundException,
} from '@nestjs/common';
import * as crypto from 'crypto';

interface RiskRule {
  id: string;
  pattern: string;
  riskLevel: number;
  action: 'allow' | 'block' | 'require_approval';
  description: string;
  enabled: boolean;
  createdAt: string;
  updatedAt: string;
}

interface PermissionMatrix {
  [role: string]: string[];
}

/**
 * Provides CRUD for risk rules and a permission matrix endpoint.
 * Rules are stored in-memory for now; a database-backed repository
 * can replace the array once the schema is defined.
 */
@Controller('api/v1/agent')
export class RiskRulesController {
  /** In-memory store seeded from CommandRiskClassifier defaults. */
  private rules: RiskRule[] = this.seedDefaultRules();

  private permissionMatrix: PermissionMatrix = {
    admin: ['manage_servers', 'execute_commands', 'view_audit', 'manage_users', 'approve_commands'],
    operator: ['execute_commands', 'view_audit'],
    viewer: ['view_audit'],
    readonly: [],
  };

  /* ---------- Risk Rules CRUD ---------- */

  @Get('risk-rules')
  listRules() {
    return { data: this.rules, total: this.rules.length };
  }

  @Post('risk-rules')
  createRule(@Body() body: any) {
    const now = new Date().toISOString();
    const rule: RiskRule = {
      id: crypto.randomUUID(),
      pattern: body.pattern,
      riskLevel: body.riskLevel ?? 0,
      action: body.action ?? 'allow',
      description: body.description ?? '',
      enabled: body.enabled ?? true,
      createdAt: now,
      updatedAt: now,
    };
    this.rules.push(rule);
    return rule;
  }

  @Put('risk-rules/:id')
  updateRule(@Param('id') id: string, @Body() body: any) {
    const rule = this.rules.find((r) => r.id === id);
    if (!rule) {
      throw new NotFoundException(`Risk rule ${id} not found`);
    }
    if (body.pattern !== undefined) rule.pattern = body.pattern;
    if (body.riskLevel !== undefined) rule.riskLevel = body.riskLevel;
    if (body.action !== undefined) rule.action = body.action;
    if (body.description !== undefined) rule.description = body.description;
    if (body.enabled !== undefined) rule.enabled = body.enabled;
    rule.updatedAt = new Date().toISOString();
    return rule;
  }

  @Delete('risk-rules/:id')
  deleteRule(@Param('id') id: string) {
    const idx = this.rules.findIndex((r) => r.id === id);
    if (idx === -1) {
      throw new NotFoundException(`Risk rule ${id} not found`);
    }
    this.rules.splice(idx, 1);
    return { success: true };
  }

  /* ---------- Permissions ---------- */

  @Get('permissions')
  getPermissions() {
    return this.permissionMatrix;
  }

  @Put('permissions')
  updatePermissions(@Body() body: PermissionMatrix) {
    this.permissionMatrix = { ...this.permissionMatrix, ...body };
    return this.permissionMatrix;
  }

  /* ---------- Helpers ---------- */

  private seedDefaultRules(): RiskRule[] {
    const now = new Date().toISOString();
    return [
      { id: crypto.randomUUID(), pattern: 'rm\\s+-rf\\s+\\/(?!tmp)', riskLevel: 3, action: 'block', description: 'Block recursive delete on root paths', enabled: true, createdAt: now, updatedAt: now },
      { id: crypto.randomUUID(), pattern: 'mkfs', riskLevel: 3, action: 'block', description: 'Block filesystem format commands', enabled: true, createdAt: now, updatedAt: now },
      { id: crypto.randomUUID(), pattern: 'dd\\s+if=.*of=\\/dev', riskLevel: 3, action: 'block', description: 'Block raw device writes', enabled: true, createdAt: now, updatedAt: now },
      { id: crypto.randomUUID(), pattern: 'systemctl\\s+(stop|restart|disable)', riskLevel: 2, action: 'require_approval', description: 'Require approval for service management', enabled: true, createdAt: now, updatedAt: now },
      { id: crypto.randomUUID(), pattern: 'docker\\s+(rm|stop|kill)', riskLevel: 2, action: 'require_approval', description: 'Require approval for destructive Docker commands', enabled: true, createdAt: now, updatedAt: now },
      { id: crypto.randomUUID(), pattern: 'reboot|shutdown', riskLevel: 2, action: 'require_approval', description: 'Require approval for reboot/shutdown', enabled: true, createdAt: now, updatedAt: now },
      { id: crypto.randomUUID(), pattern: 'echo\\s+.*>|tee\\s|sed\\s+-i|mv\\s|cp\\s', riskLevel: 1, action: 'allow', description: 'Low-risk write operations', enabled: true, createdAt: now, updatedAt: now },
    ];
  }
}
