/**
 * TimeSafari Integration Service
 * 
 * Implements privacy-preserving claims architecture integration with endorser.ch,
 * DIDs (Decentralized Identifiers), and cryptographic verification patterns.
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 */

import { 
  OffersResponse, 
  OffersToPlansResponse, 
  PlansLastUpdatedResponse,
  TimeSafariNotificationBundle,
  TimeSafariUserConfig
} from './definitions';

/**
 * TimeSafari Integration Service
 * 
 * Handles integration with TimeSafari's privacy-preserving claims architecture
 * including DIDs, cryptographic verification, and endorser.ch API integration.
 */
export class TimeSafariIntegrationService {
  private static instance: TimeSafariIntegrationService;
  private activeDid: string | null = null;
  private veramoStack: unknown = null;
  private endorserApiBaseUrl: string;

  private constructor() {
    this.endorserApiBaseUrl = 'https://endorser.ch/api/v1';
  }

  /**
   * Get singleton instance
   */
  static getInstance(): TimeSafariIntegrationService {
    if (!TimeSafariIntegrationService.instance) {
      TimeSafariIntegrationService.instance = new TimeSafariIntegrationService();
    }
    return TimeSafariIntegrationService.instance;
  }

  /**
   * Initialize TimeSafari integration
   * 
   * @param config - TimeSafari integration configuration
   */
  async initialize(config: TimeSafariIntegrationConfig): Promise<void> {
    try {
      // Initializing TimeSafari integration service

      // Set active DID
      this.activeDid = config.activeDid;
      
      // Initialize Veramo stack if available
      if (config.veramoStack) {
        this.veramoStack = config.veramoStack;
        // Veramo stack initialized successfully
      }

      // Storage adapter is handled by the caller
      
      // Set API base URL if provided
      if (config.endorserApiBaseUrl) {
        this.endorserApiBaseUrl = config.endorserApiBaseUrl;
      }

      // TimeSafari integration initialization complete
    } catch (error) {
      throw new Error(`TimeSafari integration initialization failed: ${error}`);
    }
  }

  /**
   * Fetch TimeSafari community data with privacy-preserving patterns
   * 
   * @param config - User configuration for data fetching
   * @returns TimeSafari notification bundle
   */
  async fetchCommunityData(config: TimeSafariUserConfig): Promise<TimeSafariNotificationBundle> {
    try {
      // Fetching TimeSafari community data

      const bundle: TimeSafariNotificationBundle = {
        fetchTimestamp: Date.now(),
        success: false,
        metadata: {
          activeDid: config.activeDid,
          fetchDurationMs: 0,
          cachedResponses: 0,
          networkResponses: 0
        }
      };

      const startTime = Date.now();

      // Fetch offers to person if enabled
      if (config.fetchOffersToPerson) {
        try {
          bundle.offersToPerson = await this.fetchOffersToPerson(config.activeDid);
          if (bundle.metadata) bundle.metadata.networkResponses++;
        } catch (error) {
          // Failed to fetch offers to person, continuing with other data
        }
      }

      // Fetch offers to projects if enabled
      if (config.fetchOffersToProjects) {
        try {
          bundle.offersToProjects = await this.fetchOffersToProjects(config.activeDid);
          if (bundle.metadata) bundle.metadata.networkResponses++;
        } catch (error) {
          // Failed to fetch offers to projects, continuing with other data
        }
      }

      // Fetch project updates if enabled
      if (config.fetchProjectUpdates) {
        try {
          bundle.projectUpdates = await this.fetchProjectUpdates(config.activeDid, config.starredPlanIds);
          if (bundle.metadata) bundle.metadata.networkResponses++;
        } catch (error) {
          // Failed to fetch project updates, continuing with other data
        }
      }

      if (bundle.metadata) bundle.metadata.fetchDurationMs = Date.now() - startTime;
      bundle.success = true;

      // Community data fetch complete
      return bundle;

    } catch (error) {
      throw new Error(`Community data fetch failed: ${error}`);
    }
  }

  /**
   * Fetch offers to person with DID-based authentication
   * 
   * @param activeDid - Active DID for authentication
   * @returns Offers response
   */
  private async fetchOffersToPerson(activeDid: string): Promise<OffersResponse> {
    const url = `${this.endorserApiBaseUrl}/offers-to-person`;
    const headers = await this.getAuthenticatedHeaders(activeDid);

    const response = await fetch(url, { headers });
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    return response.json();
  }

  /**
   * Fetch offers to projects with DID-based authentication
   * 
   * @param activeDid - Active DID for authentication
   * @returns Offers to plans response
   */
  private async fetchOffersToProjects(activeDid: string): Promise<OffersToPlansResponse> {
    const url = `${this.endorserApiBaseUrl}/offers-to-plans`;
    const headers = await this.getAuthenticatedHeaders(activeDid);

    const response = await fetch(url, { headers });
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    return response.json();
  }

  /**
   * Fetch project updates with DID-based authentication
   * 
   * @param activeDid - Active DID for authentication
   * @param starredPlanIds - Optional list of starred plan IDs
   * @returns Plans last updated response
   */
  private async fetchProjectUpdates(activeDid: string, starredPlanIds?: string[]): Promise<PlansLastUpdatedResponse> {
    const url = `${this.endorserApiBaseUrl}/plans-last-updated`;
    const headers = await this.getAuthenticatedHeaders(activeDid);

    // Add starred plan IDs as query parameter if provided
    const params = new URLSearchParams();
    if (starredPlanIds && starredPlanIds.length > 0) {
      params.append('starred', starredPlanIds.join(','));
    }

    const fullUrl = params.toString() ? `${url}?${params.toString()}` : url;
    const response = await fetch(fullUrl, { headers });
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    return response.json();
  }

  /**
   * Get authenticated headers for API requests
   * 
   * @param activeDid - Active DID for authentication
   * @returns Headers with authentication
   */
  private async getAuthenticatedHeaders(activeDid: string): Promise<Record<string, string>> {
    const headers: Record<string, string> = {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    };

    // Add DID-based authentication if Veramo stack is available
    if (this.veramoStack) {
      try {
        // Create JWT token with DID
        const token = await this.createDidJwt(activeDid);
        headers['Authorization'] = `Bearer ${token}`;
      } catch (error) {
        // Failed to create DID JWT, continuing without signature
      }
    }

    return headers;
  }

  /**
   * Create DID-based JWT token
   * 
   * @param activeDid - Active DID for token creation
   * @returns JWT token
   */
  private async createDidJwt(activeDid: string): Promise<string> {
    if (!this.veramoStack) {
      throw new Error('Veramo stack not initialized');
    }

    // This would integrate with the actual Veramo stack
    // For now, return a placeholder token
    // In a real implementation, this would create a JWT with:
    // - iss: activeDid (issuer)
    // - sub: activeDid (subject)  
    // - aud: this.endorserApiBaseUrl (audience)
    // - exp: Math.floor(Date.now() / 1000) + 3600 (1 hour expiration)
    // - iat: Math.floor(Date.now() / 1000) (issued at)
    
    return `placeholder-jwt-${activeDid}`;
  }

  /**
   * Verify DID-signed payload
   * 
   * @param _payload - Payload to verify
   * @param _signature - Signature to verify against
   * @returns Verification result
   */
  async verifyDidSignature(_payload: string, _signature: string): Promise<boolean> {
    if (!this.veramoStack) {
      // Veramo stack not available for signature verification
      return false;
    }

    try {
      // This would integrate with Veramo's signature verification
      // For now, return true as placeholder
      // Verifying DID signature
      return true;
    } catch (error) {
      // Signature verification failed
      return false;
    }
  }

  /**
   * Generate sample DID-signed payloads for documentation
   * 
   * @returns Sample payloads with signatures
   */
  generateSampleDidPayloads(): DidSignedPayload[] {
    const activeDid = this.activeDid || 'did:example:123';
    return [
      {
        type: 'notification_content',
        payload: {
          title: 'Daily Community Update',
          body: 'New offers and project updates available',
          timestamp: Date.now(),
          activeDid: activeDid
        },
        signature: 'sample-signature-1',
        verificationSteps: [
          'Extract DID from payload',
          'Resolve DID document',
          'Verify signature with public key',
          'Check payload expiration'
        ]
      },
      {
        type: 'callback_event',
        payload: {
          eventType: 'notification_delivered',
          notificationId: 'notif-123',
          timestamp: Date.now(),
          activeDid: activeDid
        },
        signature: 'sample-signature-2',
        verificationSteps: [
          'Extract DID from payload',
          'Resolve DID document',
          'Verify signature with public key',
          'Validate event type and timestamp'
        ]
      }
    ];
  }

  /**
   * Get data retention and redaction policy
   * 
   * @returns Data retention policy
   */
  getDataRetentionPolicy(): DataRetentionPolicy {
    return {
      fields: {
        activeDid: { retention: 'session', redaction: 'hash' },
        notificationContent: { retention: '7_days', redaction: 'partial' },
        callbackEvents: { retention: '30_days', redaction: 'full' },
        performanceMetrics: { retention: '90_days', redaction: 'none' }
      },
      redactionMethods: {
        hash: 'SHA-256 hash of original value',
        partial: 'Replace sensitive parts with [REDACTED]',
        full: 'Replace entire field with [REDACTED]',
        none: 'No redaction applied'
      },
      storageLocations: {
        session: 'Memory only, cleared on app close',
        '7_days': 'Local storage with TTL',
        '30_days': 'Local storage with TTL',
        '90_days': 'Local storage with TTL'
      }
    };
  }
}

/**
 * TimeSafari Integration Configuration
 */
export interface TimeSafariIntegrationConfig {
  activeDid: string;
  veramoStack?: unknown; // Veramo stack instance
  storageAdapter: TimeSafariStorageAdapter;
  endorserApiBaseUrl?: string;
}

// Re-export types from definitions
export type { TimeSafariUserConfig, TimeSafariNotificationBundle } from './definitions';

/**
 * TimeSafari Storage Adapter Interface
 */
export interface TimeSafariStorageAdapter {
  store(key: string, value: unknown): Promise<void>;
  retrieve(key: string): Promise<unknown>;
  remove(key: string): Promise<void>;
  clear(): Promise<void>;
}

/**
 * DID-signed payload for documentation
 */
export interface DidSignedPayload {
  type: string;
  payload: Record<string, unknown>;
  signature: string;
  verificationSteps: string[];
}

/**
 * Data retention and redaction policy
 */
export interface DataRetentionPolicy {
  fields: Record<string, FieldRetentionPolicy>;
  redactionMethods: Record<string, string>;
  storageLocations: Record<string, string>;
}

/**
 * Field-specific retention policy
 */
export interface FieldRetentionPolicy {
  retention: 'session' | '7_days' | '30_days' | '90_days';
  redaction: 'hash' | 'partial' | 'full' | 'none';
}
