/**
 * ConsentAPI - Kommunikation mit dem Consent-Backend
 *
 * Sendet Consent-Entscheidungen an das Backend zur
 * revisionssicheren Speicherung.
 */

import type {
  ConsentConfig,
  ConsentState,
  ConsentAPIResponse,
  SiteConfigResponse,
} from '../types';

/**
 * Request-Payload fuer Consent-Speicherung
 */
interface SaveConsentRequest {
  siteId: string;
  userId?: string;
  deviceFingerprint: string;
  consent: ConsentState;
  metadata?: {
    userAgent?: string;
    language?: string;
    screenResolution?: string;
    platform?: string;
    appVersion?: string;
  };
}

/**
 * ConsentAPI - Backend-Kommunikation
 */
export class ConsentAPI {
  private config: ConsentConfig;
  private baseUrl: string;

  constructor(config: ConsentConfig) {
    this.config = config;
    this.baseUrl = config.apiEndpoint.replace(/\/$/, '');
  }

  /**
   * Consent speichern
   */
  async saveConsent(request: SaveConsentRequest): Promise<ConsentAPIResponse> {
    const payload = {
      ...request,
      metadata: {
        userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : '',
        language: typeof navigator !== 'undefined' ? navigator.language : '',
        screenResolution:
          typeof window !== 'undefined'
            ? `${window.screen.width}x${window.screen.height}`
            : '',
        platform: 'web',
        ...request.metadata,
      },
    };

    const response = await this.fetch('/consent', {
      method: 'POST',
      body: JSON.stringify(payload),
    });

    if (!response.ok) {
      throw new Error(`Failed to save consent: ${response.status}`);
    }

    return response.json();
  }

  /**
   * Consent abrufen
   */
  async getConsent(
    siteId: string,
    deviceFingerprint: string
  ): Promise<ConsentState | null> {
    const params = new URLSearchParams({
      siteId,
      deviceFingerprint,
    });

    const response = await this.fetch(`/consent?${params}`);

    if (response.status === 404) {
      return null;
    }

    if (!response.ok) {
      throw new Error(`Failed to get consent: ${response.status}`);
    }

    const data = await response.json();
    return data.consent;
  }

  /**
   * Consent widerrufen
   */
  async revokeConsent(consentId: string): Promise<void> {
    const response = await this.fetch(`/consent/${consentId}`, {
      method: 'DELETE',
    });

    if (!response.ok) {
      throw new Error(`Failed to revoke consent: ${response.status}`);
    }
  }

  /**
   * Site-Konfiguration abrufen
   */
  async getSiteConfig(siteId: string): Promise<SiteConfigResponse> {
    const response = await this.fetch(`/config/${siteId}`);

    if (!response.ok) {
      throw new Error(`Failed to get site config: ${response.status}`);
    }

    return response.json();
  }

  /**
   * Consent-Historie exportieren (DSGVO Art. 20)
   */
  async exportConsent(userId: string): Promise<unknown> {
    const params = new URLSearchParams({ userId });
    const response = await this.fetch(`/consent/export?${params}`);

    if (!response.ok) {
      throw new Error(`Failed to export consent: ${response.status}`);
    }

    return response.json();
  }

  // ===========================================================================
  // Internal Methods
  // ===========================================================================

  /**
   * Fetch mit Standard-Headers
   */
  private async fetch(
    path: string,
    options: RequestInit = {}
  ): Promise<Response> {
    const url = `${this.baseUrl}${path}`;

    const headers: HeadersInit = {
      'Content-Type': 'application/json',
      Accept: 'application/json',
      ...this.getSignatureHeaders(),
      ...(options.headers || {}),
    };

    try {
      const response = await fetch(url, {
        ...options,
        headers,
        credentials: 'include',
      });

      this.log(`${options.method || 'GET'} ${path}:`, response.status);
      return response;
    } catch (error) {
      this.log('Fetch error:', error);
      throw error;
    }
  }

  /**
   * Signatur-Headers generieren (HMAC)
   */
  private getSignatureHeaders(): Record<string, string> {
    const timestamp = Math.floor(Date.now() / 1000).toString();

    // Einfache Signatur fuer Client-Side
    // In Produktion: Server-seitige Validierung mit echtem HMAC
    const signature = this.simpleHash(`${this.config.siteId}:${timestamp}`);

    return {
      'X-Consent-Timestamp': timestamp,
      'X-Consent-Signature': `sha256=${signature}`,
    };
  }

  /**
   * Einfache Hash-Funktion (djb2)
   */
  private simpleHash(str: string): string {
    let hash = 5381;
    for (let i = 0; i < str.length; i++) {
      hash = (hash * 33) ^ str.charCodeAt(i);
    }
    return (hash >>> 0).toString(16);
  }

  /**
   * Debug-Logging
   */
  private log(...args: unknown[]): void {
    if (this.config.debug) {
      console.log('[ConsentAPI]', ...args);
    }
  }
}

export default ConsentAPI;
