import express, { Router } from 'express';
import { ApiKeyService } from '../../services/ApiKeyService';
import { validateApiKey } from '../../middleware/auth/validateApiKey';
import { requireMasterKey } from '../../middleware/auth/requireMasterKey';

const router: Router = express.Router();
const apiKeyService = new ApiKeyService();

// All admin routes require master key
router.use(validateApiKey);
router.use(requireMasterKey);

/**
 * Create a new API key
 * POST /api/admin/keys
 */
router.post('/', async (req, res): Promise<void> => {
  try {
    const {
      type,
      projectId: _projectId,
      organizationId: _organizationId,
      organizationSlug,
      projectSlug,
      organizationName,
      projectName,
      name,
      expiresInDays,
    } = req.body;

    // Validation
    if (!type || !['master', 'project'].includes(type)) {
      res.status(400).json({
        error: 'Invalid type',
        message: 'Type must be either "master" or "project"',
      });
      return;
    }

    if (type === 'project' && !projectSlug) {
      res.status(400).json({
        error: 'Missing projectSlug',
        message: 'Project keys require a projectSlug',
      });
      return;
    }

    if (type === 'project' && !organizationSlug) {
      res.status(400).json({
        error: 'Missing organizationSlug',
        message: 'Project keys require an organizationSlug',
      });
      return;
    }

    // Create key
    let result;

    if (type === 'master') {
      result = await apiKeyService.createMasterKey(name, req.apiKey!.id);
    } else {
      // Get or create organization and project
      const finalOrgId = await apiKeyService.getOrCreateOrganization(
        organizationSlug,
        organizationName,
      );

      const finalProjectId = await apiKeyService.getOrCreateProject(
        finalOrgId,
        projectSlug,
        projectName,
      );

      result = await apiKeyService.createProjectKey(
        finalProjectId,
        finalOrgId,
        name,
        req.apiKey!.id,
        expiresInDays || 90,
      );
    }

    console.log(
      `[${new Date().toISOString()}] New API key created by admin: ${result.metadata.id} (${result.metadata.keyType}) - by: ${req.apiKey!.id}`,
    );

    res.status(201).json({
      apiKey: result.key,
      metadata: {
        id: result.metadata.id,
        type: result.metadata.keyType,
        projectId: result.metadata.projectId,
        organizationId: result.metadata.organizationId,
        name: result.metadata.name,
        expiresAt: result.metadata.expiresAt,
        scopes: result.metadata.scopes,
        createdAt: result.metadata.createdAt,
      },
      message: 'IMPORTANT: Save this key securely. You will not see it again!',
    });
  } catch (error) {
    console.error(`[${new Date().toISOString()}] Error creating API key:`, error);
    res.status(500).json({
      error: 'Failed to create API key',
      message: 'An error occurred while creating the key',
    });
  }
});

/**
 * List all API keys
 * GET /api/admin/keys
 */
router.get('/', async (req, res) => {
  try {
    const keys = await apiKeyService.listKeys();

    // Format response with nested objects, ISO dates, and no sensitive data
    const safeKeys = keys.map((key) => ({
      id: key.id,
      type: key.keyType,
      name: key.name,
      scopes: key.scopes,
      isActive: key.isActive,
      createdAt: key.createdAt.toISOString(),
      expiresAt: key.expiresAt ? key.expiresAt.toISOString() : null,
      lastUsedAt: key.lastUsedAt ? key.lastUsedAt.toISOString() : null,
      createdBy: key.createdBy,
      organization: key.organization,
      project: key.project,
    }));

    console.log(
      `[${new Date().toISOString()}] API keys listed by admin: ${req.apiKey!.id} - returned ${safeKeys.length} keys`,
    );

    res.json({
      keys: safeKeys,
      total: safeKeys.length,
    });
  } catch (error) {
    console.error(`[${new Date().toISOString()}] Error listing API keys:`, error);
    res.status(500).json({
      error: 'Failed to list keys',
      message: 'An error occurred while fetching keys',
    });
  }
});

/**
 * Revoke an API key
 * DELETE /api/admin/keys/:keyId
 */
router.delete('/:keyId', async (req, res): Promise<void> => {
  try {
    const { keyId } = req.params;

    const success = await apiKeyService.revokeKey(keyId);

    if (!success) {
      res.status(404).json({
        error: 'Key not found',
        message: 'The specified API key does not exist',
      });
      return;
    }

    console.log(`[${new Date().toISOString()}] API key revoked: ${keyId} - by: ${req.apiKey!.id}`);

    res.json({
      message: 'API key revoked successfully',
      keyId,
    });
  } catch (error) {
    console.error(`[${new Date().toISOString()}] Error revoking API key:`, error);
    res.status(500).json({
      error: 'Failed to revoke key',
      message: 'An error occurred while revoking the key',
    });
  }
});

export default router;
