/**
 * Vault Secrets API Client
 *
 * API client for interacting with vault secrets endpoints
 */

import {
  Secret,
  SecretWithValue,
  SecretHistory,
  CreateSecretRequest,
  UpdateSecretRequest,
  ListSecretsQuery,
  ListSecretsResponse,
  ApiError,
} from '../types/secrets';

const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:8080';

class SecretsApiError extends Error {
  constructor(public error: ApiError) {
    super(error.message);
    this.name = 'SecretsApiError';
  }
}

/**
 * Get authorization token from storage
 */
function getAuthToken(): string | null {
  return localStorage.getItem('auth_token');
}

/**
 * Make authenticated API request
 */
async function apiRequest<T>(
  endpoint: string,
  options: RequestInit = {}
): Promise<T> {
  const token = getAuthToken();

  const headers: HeadersInit = {
    'Content-Type': 'application/json',
    ...options.headers,
  };

  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
    ...options,
    headers,
  });

  if (!response.ok) {
    const errorData: ApiError = await response.json();
    throw new SecretsApiError(errorData);
  }

  // Handle 204 No Content
  if (response.status === 204) {
    return null as T;
  }

  return response.json();
}

/**
 * Secrets API Client
 */
export const secretsApi = {
  /**
   * Create a new secret
   */
  async createSecret(request: CreateSecretRequest): Promise<Secret> {
    return apiRequest<Secret>('/api/v1/secrets/vault', {
      method: 'POST',
      body: JSON.stringify(request),
    });
  },

  /**
   * Get a secret value (decrypted)
   */
  async getSecret(
    path: string,
    version?: number,
    context?: string
  ): Promise<SecretWithValue> {
    const params = new URLSearchParams();
    if (version !== undefined) {
      params.append('version', version.toString());
    }
    if (context) {
      params.append('context', context);
    }

    const queryString = params.toString();
    const endpoint = `/api/v1/secrets/vault/${encodeURIComponent(path)}${
      queryString ? `?${queryString}` : ''
    }`;

    return apiRequest<SecretWithValue>(endpoint);
  },

  /**
   * List secrets (metadata only)
   */
  async listSecrets(query?: ListSecretsQuery): Promise<ListSecretsResponse> {
    const params = new URLSearchParams();
    if (query?.prefix) {
      params.append('prefix', query.prefix);
    }
    if (query?.limit !== undefined) {
      params.append('limit', query.limit.toString());
    }
    if (query?.offset !== undefined) {
      params.append('offset', query.offset.toString());
    }

    const queryString = params.toString();
    const endpoint = `/api/v1/secrets/vault${queryString ? `?${queryString}` : ''}`;

    return apiRequest<ListSecretsResponse>(endpoint);
  },

  /**
   * Update a secret (creates new version)
   */
  async updateSecret(path: string, request: UpdateSecretRequest): Promise<Secret> {
    return apiRequest<Secret>(`/api/v1/secrets/vault/${encodeURIComponent(path)}`, {
      method: 'PUT',
      body: JSON.stringify(request),
    });
  },

  /**
   * Delete a secret
   */
  async deleteSecret(path: string): Promise<void> {
    return apiRequest<void>(`/api/v1/secrets/vault/${encodeURIComponent(path)}`, {
      method: 'DELETE',
    });
  },

  /**
   * Get secret history/versions
   */
  async getSecretHistory(path: string): Promise<SecretHistory> {
    return apiRequest<SecretHistory>(
      `/api/v1/secrets/vault/${encodeURIComponent(path)}/history`
    );
  },

  /**
   * Restore a specific version of a secret
   */
  async restoreSecretVersion(path: string, version: number): Promise<Secret> {
    return apiRequest<Secret>(
      `/api/v1/secrets/vault/${encodeURIComponent(path)}/versions/${version}/restore`,
      {
        method: 'POST',
      }
    );
  },
};

export { SecretsApiError };
