/**
 * API Key Management Service
 *
 * Handles creation, verification, and management of API keys for WordPress plugin authentication
 */

import { PrismaClient } from '@prisma/client';
import { generateApiKey, hashApiKey } from '../utils/encryption';
import { logger } from '../utils/logger';

const prisma = new PrismaClient();

// Response Types
export interface ApiKeyData {
  id: string;
  userId: string;
  name: string;
  prefix: string;
  isActive: boolean;
  lastUsedAt: Date | null;
  createdAt: Date;
}

export interface ApiKeyResponse extends ApiKeyData {
  key?: string; // Only returned on creation
}

export interface ApiKeyVerificationResult {
  valid: boolean;
  keyData?: ApiKeyData;
}

/**
 * Create a new API key for a user
 * Returns the full key (only shown once) and metadata
 */
export async function createApiKey(userId: string, name: string): Promise<ApiKeyResponse> {
  try {
    // Generate new API key
    const { key, hash, prefix } = generateApiKey('sk_live');

    // Store in database
    const apiKey = await prisma.apiKey.create({
      data: {
        user_id: userId,
        key_hash: hash,
        prefix,
        name,
        is_active: true,
      },
    });

    logger.info('API key created', { userId, keyId: apiKey.id, name });

    return {
      id: apiKey.id,
      userId: apiKey.user_id,
      name: apiKey.name,
      prefix: apiKey.prefix,
      isActive: apiKey.is_active,
      lastUsedAt: apiKey.last_used_at,
      createdAt: apiKey.created_at,
      key, // Full key returned only on creation
    };
  } catch (error) {
    logger.error('Failed to create API key', { error, userId, name });
    throw new Error('Failed to create API key');
  }
}

/**
 * Verify API key and return associated user data
 * Updates last_used_at timestamp on successful verification
 */
export async function verifyApiKey(key: string): Promise<ApiKeyVerificationResult> {
  try {
    // Hash the provided key
    const keyHash = hashApiKey(key);

    // Find matching API key
    const apiKey = await prisma.apiKey.findFirst({
      where: {
        key_hash: keyHash,
        is_active: true,
      },
      include: {
        user: {
          select: {
            id: true,
            email: true,
            status: true,
            subscriptions: {
              select: {
                plan_tier: true,
                status: true,
              },
            },
          },
        },
      },
    });

    if (!apiKey) {
      logger.warn('Invalid API key attempt');
      return { valid: false };
    }

    // Check if user is active
    if (apiKey.user.status !== 'active') {
      logger.warn('API key used by inactive user', { userId: apiKey.user_id });
      return { valid: false };
    }

    // Update last_used_at timestamp (fire and forget)
    prisma.apiKey
      .update({
        where: { id: apiKey.id },
        data: { last_used_at: new Date() },
      })
      .catch((error) => {
        logger.error('Failed to update API key last_used_at', { error, keyId: apiKey.id });
      });

    logger.debug('API key verified', { userId: apiKey.user_id, keyId: apiKey.id });

    return {
      valid: true,
      keyData: {
        id: apiKey.id,
        userId: apiKey.user_id,
        name: apiKey.name,
        prefix: apiKey.prefix,
        isActive: apiKey.is_active,
        lastUsedAt: apiKey.last_used_at,
        createdAt: apiKey.created_at,
      },
    };
  } catch (error) {
    logger.error('Failed to verify API key', { error });
    return { valid: false };
  }
}

/**
 * Revoke (deactivate) an API key
 */
export async function revokeApiKey(keyId: string, userId: string): Promise<boolean> {
  try {
    const { count } = await prisma.apiKey.updateMany({
      where: {
        id: keyId,
        user_id: userId,
      },
      data: { is_active: false },
    });

    if (count === 0) {
      logger.warn('API key not found or not owned by user', { keyId, userId });
      return false;
    }

    logger.info('API key revoked', { userId, keyId });
    return true;
  } catch (error) {
    logger.error('Failed to revoke API key', { error, keyId, userId });
    throw new Error('Failed to revoke API key');
  }
}

/**
 * Get all API keys for a user
 */
export async function getUserApiKeys(userId: string): Promise<ApiKeyData[]> {
  try {
    const apiKeys = await prisma.apiKey.findMany({
      where: {
        user_id: userId,
      },
      orderBy: {
        created_at: 'desc',
      },
    });

    return apiKeys.map((key) => ({
      id: key.id,
      userId: key.user_id,
      name: key.name,
      prefix: key.prefix,
      isActive: key.is_active,
      lastUsedAt: key.last_used_at,
      createdAt: key.created_at,
    }));
  } catch (error) {
    logger.error('Failed to get user API keys', { error, userId });
    throw new Error('Failed to get user API keys');
  }
}

/**
 * Delete an API key permanently
 */
export async function deleteApiKey(keyId: string, userId: string): Promise<boolean> {
  try {
    const apiKey = await prisma.apiKey.findFirst({
      where: {
        id: keyId,
        user_id: userId,
      },
    });

    if (!apiKey) {
      logger.warn('API key not found or not owned by user', { keyId, userId });
      return false;
    }

    await prisma.apiKey.delete({
      where: { id: keyId },
    });

    logger.info('API key deleted', { userId, keyId });
    return true;
  } catch (error) {
    logger.error('Failed to delete API key', { error, keyId, userId });
    throw new Error('Failed to delete API key');
  }
}
