import { Router, Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { authenticate } from '../../middleware/auth.middleware';
import { requireRole } from '../../middleware/rbac.middleware';
import { validate } from '../../middleware/validate';
import { updateEnvFile } from '../../services/env-writer.service';
import { dockerService } from '../../services/docker.service';
import { env } from '../../config/env';
import { logger } from '../../utils/logger';

const router = Router();

// ─── Schemas ─────────────────────────────────────────────────────────

const registerSchema = z.object({
  ccpUrl: z.string().url().regex(/^https?:\/\//, 'Must be a valid URL'),
  inviteCode: z.string().min(4).max(20),
  agentUrl: z.string().url().regex(/^https?:\/\//, 'Must be a valid URL'),
});

// ─── GET /api/ccp-registration/status ────────────────────────────────

/**
 * Check current CCP registration status by reading env vars.
 */
router.get(
  '/status',
  authenticate,
  requireRole('SUPER_ADMIN'),
  async (_req: Request, res: Response, next: NextFunction) => {
    try {
      const ccpUrl = env.CCP_URL || '';
      const agentUrl = env.CCP_AGENT_URL || '';
      const enabled = env.ENABLE_CCP_AGENT === 'true';

      // Check if agent container is running
      let agentRunning = false;
      try {
        const status = await dockerService.getContainerStatus('ccp-agent');
        agentRunning = status.running;
      } catch {
        // Container doesn't exist or isn't running
      }

      res.json({
        registered: enabled && !!ccpUrl,
        ccpUrl: ccpUrl || null,
        agentUrl: agentUrl || null,
        agentRunning,
      });
    } catch (err) {
      next(err);
    }
  }
);

// ─── POST /api/ccp-registration/register ─────────────────────────────

/**
 * Register this instance with a CCP.
 * Updates .env and starts the ccp-agent container.
 */
router.post(
  '/register',
  authenticate,
  requireRole('SUPER_ADMIN'),
  validate(registerSchema),
  async (req: Request, res: Response, next: NextFunction) => {
    try {
      const { ccpUrl, inviteCode, agentUrl } = req.body;

      logger.info(`[ccp-registration] Registering with CCP at ${ccpUrl}`);

      // Step 1: Update .env with CCP configuration
      const envResult = updateEnvFile({
        ENABLE_CCP_AGENT: 'true',
        CCP_URL: ccpUrl,
        CCP_INVITE_CODE: inviteCode,
        CCP_AGENT_URL: agentUrl,
      });

      if (!envResult.success) {
        res.status(500).json({
          error: { message: `Failed to update .env: ${envResult.error}`, code: 'ENV_WRITE_FAILED' },
        });
        return;
      }

      // Step 2: Ensure ccp-agent is in COMPOSE_PROFILES
      const profileResult = updateEnvFile({
        COMPOSE_PROFILES: addProfile(env.COMPOSE_PROFILES || '', 'ccp-agent'),
      });

      if (!profileResult.success) {
        logger.warn(`[ccp-registration] Failed to update COMPOSE_PROFILES: ${profileResult.error}`);
      }

      // Step 3: Start the ccp-agent container
      let agentStarted = false;
      let agentOutput = '';
      try {
        const result = await dockerService.restartContainer('ccp-agent');
        agentStarted = result.success;
        agentOutput = result.output;
      } catch (err) {
        agentOutput = (err as Error).message;
        logger.warn(`[ccp-registration] Failed to start agent: ${agentOutput}`);
      }

      logger.info(`[ccp-registration] Registration initiated: env updated, agent ${agentStarted ? 'started' : 'failed to start'}`);

      res.json({
        success: true,
        envUpdated: true,
        agentStarted,
        agentOutput: agentStarted ? undefined : agentOutput,
        message: agentStarted
          ? 'Registration initiated — agent is phoning home to the CCP. Waiting for admin approval.'
          : 'Environment configured but agent container failed to start. Check docker compose logs.',
      });
    } catch (err) {
      next(err);
    }
  }
);

// ─── POST /api/ccp-registration/unregister ───────────────────────────

/**
 * Remove CCP registration and stop the agent.
 */
router.post(
  '/unregister',
  authenticate,
  requireRole('SUPER_ADMIN'),
  async (_req: Request, res: Response, next: NextFunction) => {
    try {
      logger.info('[ccp-registration] Unregistering from CCP');

      // Clear env vars
      updateEnvFile({
        ENABLE_CCP_AGENT: 'false',
        CCP_URL: '',
        CCP_INVITE_CODE: '',
        CCP_AGENT_URL: '',
        COMPOSE_PROFILES: removeProfile(env.COMPOSE_PROFILES || '', 'ccp-agent'),
      });

      // Stop the agent container
      try {
        // Use docker compose stop instead of up -d
        const { exec } = await import('child_process');
        const { promisify } = await import('util');
        const execAsync = promisify(exec);
        await execAsync('docker compose --profile ccp-agent stop ccp-agent', {
          cwd: '/app',
          timeout: 30_000,
        });
      } catch {
        // Agent might not be running — that's fine
      }

      res.json({ success: true, message: 'CCP registration removed and agent stopped.' });
    } catch (err) {
      next(err);
    }
  }
);

// ─── Helpers ─────────────────────────────────────────────────────────

function addProfile(current: string, profile: string): string {
  const profiles = current.split(',').map(p => p.trim()).filter(Boolean);
  if (!profiles.includes(profile)) profiles.push(profile);
  return profiles.join(',');
}

function removeProfile(current: string, profile: string): string {
  return current.split(',').map(p => p.trim()).filter(p => p && p !== profile).join(',');
}

export default router;
