/**
 * TimeSafari PWA - CapacitorPlatformService Clean Integration Example
 * 
 * This example shows the ACTUAL CHANGES needed to the existing TimeSafari PWA
 * CapacitorPlatformService to add DailyNotification plugin functionality.
 * 
 * The plugin code ONLY touches Capacitor classes - no isCapacitor flags needed.
 * 
 * @author Matthew Raymer
 * @version 1.0.0
 */

// =================================================
// EXISTING TIMESAFARI PWA CODE (unchanged)
// =================================================

import { CameraDirection } from "@capacitor/camera";
import { Capacitor } from "@capacitor/core";
import {
  SQLiteConnection,
  SQLiteDBConnection,
  CapacitorSQLite,
} from "@capacitor-community/sqlite";

import { QueryExecResult } from "@/interfaces/database";
import {
  PlatformService,
  PlatformCapabilities,
} from "../PlatformService";
import { logger } from "../../utils/logger";

// =================================================
// NEW IMPORTS FOR DAILYNOTIFICATION PLUGIN
// =================================================

import { DailyNotification } from '@timesafari/daily-notification-plugin';
import { TimeSafariIntegrationService } from '@timesafari/daily-notification-plugin';

// =================================================
// EXISTING INTERFACES (unchanged)
// =================================================

interface QueuedOperation {
  type: "run" | "query" | "rawQuery";
  sql: string;
  params: unknown[];
  resolve: (value: unknown) => void;
  reject: (reason: unknown) => void;
}

// =================================================
// NEW INTERFACES FOR DAILYNOTIFICATION PLUGIN
// =================================================

interface PlanSummaryAndPreviousClaim {
  id: string;
  title: string;
  description: string;
  lastUpdated: string;
  previousClaim?: unknown;
}

interface StarredProjectsResponse {
  data: Array<PlanSummaryAndPreviousClaim>;
  hitLimit: boolean;
}

interface TimeSafariSettings {
  accountDid?: string;
  activeDid?: string;
  apiServer?: string;
  starredPlanHandleIds?: string[];
  lastAckedStarredPlanChangesJwtId?: string;
  [key: string]: unknown;
}

/**
 * EXTENDED CapacitorPlatformService with DailyNotification Integration
 * 
 * This shows the ACTUAL CHANGES needed to the existing TimeSafari PWA
 * CapacitorPlatformService class. The plugin code ONLY touches this class.
 */
export class CapacitorPlatformService implements PlatformService {
  // =================================================
  // EXISTING PROPERTIES (unchanged)
  // =================================================
  
  /** Current camera direction */
  private currentDirection: CameraDirection = CameraDirection.Rear;

  private sqlite: SQLiteConnection;
  private db: SQLiteDBConnection | null = null;
  private dbName = "timesafari.sqlite";
  private initialized = false;
  private initializationPromise: Promise<void> | null = null;
  private operationQueue: Array<QueuedOperation> = [];
  private isProcessingQueue = false;

  // =================================================
  // NEW PROPERTIES FOR DAILYNOTIFICATION PLUGIN
  // =================================================
  
  private dailyNotificationService: DailyNotification | null = null;
  private integrationService: TimeSafariIntegrationService | null = null;
  private dailyNotificationInitialized = false;
  
  // ActiveDid change tracking
  private currentActiveDid: string | null = null;

  // =================================================
  // EXISTING CONSTRUCTOR (unchanged)
  // =================================================
  
  constructor() {
    this.sqlite = new SQLiteConnection(CapacitorSQLite);
  }

  // =================================================
  // MODIFIED METHOD: Enhanced updateActiveDid with DailyNotification Integration
  // =================================================
  
  /**
   * Enhanced updateActiveDid method that handles DailyNotification plugin updates
   * 
   * This method extends the existing updateActiveDid method to also update
   * the DailyNotification plugin when the activeDid changes.
   */
  async updateActiveDid(did: string): Promise<void> {
    const oldDid = this.currentActiveDid;
    
    // Update the database (existing TimeSafari pattern)
    await this.dbExec(
      "UPDATE active_identity SET activeDid = ?, lastUpdated = datetime('now') WHERE id = 1",
      [did],
    );
    
    // Update local tracking
    this.currentActiveDid = did;
    
    // Update DailyNotification plugin if initialized
    if (this.dailyNotificationInitialized) {
      await this.updateDailyNotificationActiveDid(did, oldDid);
    }
    
    logger.debug(
      `[CapacitorPlatformService] ActiveDid updated from ${oldDid} to ${did}`
    );
  }

  // =================================================
  // NEW METHOD: Update DailyNotification Plugin ActiveDid
  // =================================================
  
  /**
   * Update DailyNotification plugin when activeDid changes
   */
  private async updateDailyNotificationActiveDid(newDid: string, oldDid: string | null): Promise<void> {
    try {
      logger.log(`[CapacitorPlatformService] Updating DailyNotification plugin activeDid from ${oldDid} to ${newDid}`);
      
      // Get new settings for the new activeDid
      const newSettings = await this.getTimeSafariSettings();
      
      // Reconfigure DailyNotification plugin with new activeDid
      await DailyNotification.configure({
        timesafariConfig: {
          activeDid: newDid,
          endpoints: {
            offersToPerson: `${newSettings.apiServer}/api/v2/offers/person`,
            offersToPlans: `${newSettings.apiServer}/api/v2/offers/plans`,
            projectsLastUpdated: `${newSettings.apiServer}/api/v2/report/plansLastUpdatedBetween`
          },
          starredProjectsConfig: {
            enabled: true,
            starredPlanHandleIds: newSettings.starredPlanHandleIds || [],
            lastAckedJwtId: newSettings.lastAckedStarredPlanChangesJwtId || '',
            fetchInterval: '0 8 * * *'
          }
        }
      });
      
      // Update TimeSafari Integration Service
      if (this.integrationService) {
        await this.integrationService.initialize({
          activeDid: newDid,
          storageAdapter: this.getTimeSafariStorageAdapter(),
          endorserApiBaseUrl: newSettings.apiServer || 'https://endorser.ch'
        });
      }
      
      logger.log(`[CapacitorPlatformService] DailyNotification plugin updated successfully for activeDid: ${newDid}`);
      
    } catch (error) {
      logger.error(`[CapacitorPlatformService] Failed to update DailyNotification plugin activeDid:`, error);
    }
  }

  // =================================================
  // NEW METHOD: Initialize DailyNotification Plugin
  // =================================================
  
  /**
   * Initialize DailyNotification plugin with TimeSafari configuration
   */
  async initializeDailyNotification(): Promise<void> {
    if (this.dailyNotificationInitialized) {
      return;
    }

    try {
      logger.log("[CapacitorPlatformService] Initializing DailyNotification plugin...");
      
      // Get current TimeSafari settings
      const settings = await this.getTimeSafariSettings();
      
      // Get current activeDid
      const currentActiveDid = await this.getCurrentActiveDid();
      
      // Configure DailyNotification plugin with TimeSafari data
      await DailyNotification.configure({
        // Basic plugin configuration
        storage: 'tiered',
        ttlSeconds: 1800,
        enableETagSupport: true,
        enableErrorHandling: true,
        enablePerformanceOptimization: true,
        
        // TimeSafari-specific configuration
        timesafariConfig: {
          // Use current activeDid
          activeDid: currentActiveDid || '',
          
          // Use existing TimeSafari API endpoints
          endpoints: {
            offersToPerson: `${settings.apiServer}/api/v2/offers/person`,
            offersToPlans: `${settings.apiServer}/api/v2/offers/plans`,
            projectsLastUpdated: `${settings.apiServer}/api/v2/report/plansLastUpdatedBetween`
          },
          
          // Configure starred projects fetching (matches existing TimeSafari pattern)
          starredProjectsConfig: {
            enabled: true,
            starredPlanHandleIds: settings.starredPlanHandleIds || [],
            lastAckedJwtId: settings.lastAckedStarredPlanChangesJwtId || '',
            fetchInterval: '0 8 * * *',  // Daily at 8 AM
            maxResults: 50,
            hitLimitHandling: 'warn'  // Same as existing TimeSafari error handling
          },
          
          // Sync configuration (optimized for TimeSafari use case)
          syncConfig: {
            enableParallel: true,
            maxConcurrent: 3,
            batchSize: 10,
            timeout: 30000,
            retryAttempts: 3
          },
          
          // Error policy (matches existing TimeSafari error handling)
          errorPolicy: {
            maxRetries: 3,
            backoffMultiplier: 2,
            activeDidChangeRetries: 5,  // Special retry for activeDid changes
            starredProjectsRetries: 3
          }
        },
        
        // Network configuration using existing TimeSafari patterns
        networkConfig: {
          baseURL: settings.apiServer || 'https://endorser.ch',
          timeout: 30000,
          retryAttempts: 3,
          retryDelay: 1000,
          maxConcurrent: 5,
          
          // Headers matching TimeSafari pattern
          defaultHeaders: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'User-Agent': 'TimeSafari-PWA/1.0.0'
          }
        },
        
        // Content fetch configuration (replaces existing loadNewStarredProjectChanges)
        contentFetch: {
          enabled: true,
          schedule: '0 8 * * *',  // Daily at 8 AM
          
          // Use existing TimeSafari request pattern
          requestConfig: {
            method: 'POST',
            url: `${settings.apiServer}/api/v2/report/plansLastUpdatedBetween`,
            headers: {
              'Authorization': 'Bearer ${jwt}',
              'X-User-DID': '${activeDid}',
              'Content-Type': 'application/json'
            },
            body: {
              planIds: '${starredPlanHandleIds}',
              afterId: '${lastAckedJwtId}'
            }
          },
          
          // Callbacks that match TimeSafari error handling
          callbacks: {
            onSuccess: this.handleStarredProjectsSuccess.bind(this),
            onError: this.handleStarredProjectsError.bind(this),
            onComplete: this.handleStarredProjectsComplete.bind(this)
          }
        }
      });
      
      // Initialize TimeSafari Integration Service
      this.integrationService = TimeSafariIntegrationService.getInstance();
      await this.integrationService.initialize({
        activeDid: currentActiveDid || '',
        storageAdapter: this.getTimeSafariStorageAdapter(),
        endorserApiBaseUrl: settings.apiServer || 'https://endorser.ch',
        
        // Use existing TimeSafari request patterns
        requestConfig: {
          baseURL: settings.apiServer || 'https://endorser.ch',
          timeout: 30000,
          retryAttempts: 3
        },
        
        // Configure starred projects fetching
        starredProjectsConfig: {
          enabled: true,
          starredPlanHandleIds: settings.starredPlanHandleIds || [],
          lastAckedJwtId: settings.lastAckedStarredPlanChangesJwtId || '',
          fetchInterval: '0 8 * * *',
          maxResults: 50
        }
      });
      
      // Schedule daily notifications
      await DailyNotification.scheduleDailyNotification({
        title: 'TimeSafari Community Update',
        body: 'You have new offers and project updates',
        time: '09:00',
        channel: 'timesafari_community_updates'
      });
      
      this.dailyNotificationInitialized = true;
      this.currentActiveDid = currentActiveDid;
      
      logger.log("[CapacitorPlatformService] DailyNotification plugin initialized successfully");
      
    } catch (error) {
      logger.error("[CapacitorPlatformService] Failed to initialize DailyNotification plugin:", error);
      throw error;
    }
  }

  // =================================================
  // NEW METHOD: Get Current ActiveDid
  // =================================================
  
  /**
   * Get current activeDid from the database
   */
  private async getCurrentActiveDid(): Promise<string | null> {
    try {
      const result = await this.dbQuery(
        "SELECT activeDid FROM active_identity WHERE id = 1"
      );
      
      if (result?.values?.length) {
        const activeDid = result.values[0][0] as string | null;
        return activeDid;
      }
      
      return null;
    } catch (error) {
      logger.error("[CapacitorPlatformService] Error getting current activeDid:", error);
      return null;
    }
  }

  // =================================================
  // NEW METHOD: Enhanced loadNewStarredProjectChanges
  // =================================================
  
  /**
   * Enhanced version of existing TimeSafari loadNewStarredProjectChanges method
   * 
   * This method replaces the existing TimeSafari PWA method with plugin-enhanced
   * functionality while maintaining the same interface and behavior.
   */
  async loadNewStarredProjectChanges(): Promise<StarredProjectsResponse> {
    // Ensure DailyNotification is initialized
    if (!this.dailyNotificationInitialized) {
      await this.initializeDailyNotification();
    }

    const settings = await this.getTimeSafariSettings();
    const currentActiveDid = await this.getCurrentActiveDid();
    
    if (!currentActiveDid || !settings.starredPlanHandleIds?.length) {
      return { data: [], hitLimit: false };
    }

    try {
      // Use plugin's enhanced fetching with same interface as existing TimeSafari code
      const starredProjectChanges = await this.integrationService?.getStarredProjectsWithChanges(
        currentActiveDid,
        settings.starredPlanHandleIds,
        settings.lastAckedStarredPlanChangesJwtId
      );
      
      if (!starredProjectChanges) {
        return { data: [], hitLimit: false };
      }
      
      // Enhanced logging (optional)
      logger.log("[CapacitorPlatformService] Starred projects loaded successfully:", {
        count: starredProjectChanges.data.length,
        hitLimit: starredProjectChanges.hitLimit,
        planIds: settings.starredPlanHandleIds.length,
        activeDid: currentActiveDid
      });
      
      return starredProjectChanges;
      
    } catch (error) {
      // Same error handling as existing TimeSafari code
      logger.warn("[CapacitorPlatformService] Failed to load starred project changes:", error);
      return { data: [], hitLimit: false };
    }
  }

  // =================================================
  // NEW METHOD: Get TimeSafari Settings
  // =================================================
  
  /**
   * Get TimeSafari settings using existing database patterns
   */
  private async getTimeSafariSettings(): Promise<TimeSafariSettings> {
    try {
      // Get current activeDid
      const currentActiveDid = await this.getCurrentActiveDid();
      
      if (!currentActiveDid) {
        return {};
      }

      // Use existing TimeSafari settings retrieval pattern
      const result = await this.dbQuery(
        "SELECT * FROM settings WHERE accountDid = ?",
        [currentActiveDid]
      );
      
      if (!result?.values?.length) {
        return {};
      }

      // Map database columns to values (existing TimeSafari pattern)
      const settings: TimeSafariSettings = {};
      result.columns.forEach((column, index) => {
        if (column !== 'id') {
          settings[column] = result.values[0][index];
        }
      });

      // Set activeDid from current value
      settings.activeDid = currentActiveDid;

      // Handle JSON field parsing (existing TimeSafari pattern)
      if (settings.starredPlanHandleIds && typeof settings.starredPlanHandleIds === 'string') {
        try {
          settings.starredPlanHandleIds = JSON.parse(settings.starredPlanHandleIds);
        } catch {
          settings.starredPlanHandleIds = [];
        }
      }

      return settings;
    } catch (error) {
      logger.error("[CapacitorPlatformService] Error getting TimeSafari settings:", error);
      return {};
    }
  }

  // =================================================
  // NEW METHOD: Get TimeSafari Storage Adapter
  // =================================================
  
  /**
   * Get TimeSafari storage adapter using existing patterns
   */
  private getTimeSafariStorageAdapter(): unknown {
    // Return existing TimeSafari storage adapter
    return {
      // Use existing TimeSafari storage patterns
      store: async (key: string, value: unknown): Promise<void> => {
        await this.dbExec(
          "INSERT OR REPLACE INTO temp (id, data) VALUES (?, ?)",
          [key, JSON.stringify(value)]
        );
      },
      
      retrieve: async (key: string): Promise<unknown> => {
        const result = await this.dbQuery(
          "SELECT data FROM temp WHERE id = ?",
          [key]
        );
        
        if (result?.values?.length) {
          try {
            return JSON.parse(result.values[0][0] as string);
          } catch {
            return null;
          }
        }
        
        return null;
      }
    };
  }

  // =================================================
  // NEW METHODS: Callback Handlers
  // =================================================
  
  /**
   * Callback handler for successful starred projects fetch
   */
  private async handleStarredProjectsSuccess(data: StarredProjectsResponse): Promise<void> {
    // Enhanced logging (optional)
    logger.log("[CapacitorPlatformService] Starred projects success callback:", {
      count: data.data.length,
      hitLimit: data.hitLimit,
      activeDid: this.currentActiveDid
    });
    
    // Store results in TimeSafari temp table for UI access
    await this.dbExec(
      "INSERT OR REPLACE INTO temp (id, data) VALUES (?, ?)",
      ['starred_projects_latest', JSON.stringify(data)]
    );
  }

  /**
   * Callback handler for starred projects fetch errors
   */
  private async handleStarredProjectsError(error: Error): Promise<void> {
    // Same error handling as existing TimeSafari code
    logger.warn("[CapacitorPlatformService] Failed to load starred project changes:", error);
    
    // Store error in TimeSafari temp table for UI access
    await this.dbExec(
      "INSERT OR REPLACE INTO temp (id, data) VALUES (?, ?)",
      ['starred_projects_error', JSON.stringify({ 
        error: error.message, 
        timestamp: Date.now(),
        activeDid: this.currentActiveDid
      })]
    );
  }

  /**
   * Callback handler for starred projects fetch completion
   */
  private async handleStarredProjectsComplete(result: unknown): Promise<void> {
    // Handle completion
    logger.log("[CapacitorPlatformService] Starred projects fetch completed:", {
      result,
      activeDid: this.currentActiveDid
    });
  }

  // =================================================
  // NEW METHOD: Get DailyNotification Status
  // =================================================
  
  /**
   * Get DailyNotification plugin status for debugging
   */
  async getDailyNotificationStatus(): Promise<{
    initialized: boolean;
    platform: string;
    capabilities: PlatformCapabilities;
    currentActiveDid: string | null;
  }> {
    return {
      initialized: this.dailyNotificationInitialized,
      platform: Capacitor.getPlatform(),
      capabilities: this.getCapabilities(),
      currentActiveDid: this.currentActiveDid
    };
  }

  // =================================================
  // MODIFIED METHOD: Enhanced initializeDatabase
  // =================================================
  
  private async initializeDatabase(): Promise<void> {
    // If already initialized, return immediately
    if (this.initialized) {
      return;
    }

    // If initialization is in progress, wait for it
    if (this.initializationPromise) {
      return this.initializationPromise;
    }

    try {
      // Start initialization
      this.initializationPromise = this._initialize();
      await this.initializationPromise;
      
      // NEW: Initialize DailyNotification after database is ready
      await this.initializeDailyNotification();
      
    } catch (error) {
      logger.error(
        "[CapacitorPlatformService] Initialize database method failed:",
        error,
      );
      this.initializationPromise = null; // Reset on failure
      throw error;
    }
  }

  // =================================================
  // EXISTING METHODS (unchanged - showing key ones)
  // =================================================
  
  private async _initialize(): Promise<void> {
    if (this.initialized) {
      return;
    }

    try {
      // Create/Open database
      this.db = await this.sqlite.createConnection(
        this.dbName,
        false,
        "no-encryption",
        1,
        false,
      );

      await this.db.open();

      // Run migrations
      await this.runCapacitorMigrations();

      this.initialized = true;
      logger.log(
        "[CapacitorPlatformService] SQLite database initialized successfully",
      );

      // Start processing the queue after initialization
      this.processQueue();
    } catch (error) {
      logger.error(
        "[CapacitorPlatformService] Error initializing SQLite database:",
        error,
      );
      throw new Error(
        "[CapacitorPlatformService] Failed to initialize database",
      );
    }
  }

  // ... (all other existing methods remain unchanged)
  
  /**
   * Gets the capabilities of the Capacitor platform
   * @returns Platform capabilities object
   */
  getCapabilities(): PlatformCapabilities {
    const platform = Capacitor.getPlatform();

    return {
      hasFileSystem: true,
      hasCamera: true,
      isMobile: true, // Capacitor is always mobile
      isIOS: platform === "ios",
      hasFileDownload: false, // Mobile platforms need sharing
      needsFileHandlingInstructions: true, // Mobile needs instructions
      isNativeApp: true,
    };
  }

  /**
   * @see PlatformService.dbQuery
   */
  async dbQuery(sql: string, params?: unknown[]): Promise<QueryExecResult> {
    await this.waitForInitialization();
    return this.queueOperation<QueryExecResult>("query", sql, params || []);
  }

  /**
   * @see PlatformService.dbExec
   */
  async dbExec(
    sql: string,
    params?: unknown[],
  ): Promise<{ changes: number; lastId?: number }> {
    await this.waitForInitialization();
    return this.queueOperation<{ changes: number; lastId?: number }>(
      "run",
      sql,
      params || [],
    );
  }

  // ... (all other existing methods remain unchanged)
  
  /**
   * Checks if running on Capacitor platform.
   * @returns true, as this is the Capacitor implementation
   */
  isCapacitor(): boolean {
    return true;
  }

  /**
   * Checks if running on Electron platform.
   * @returns false, as this is Capacitor, not Electron
   */
  isElectron(): boolean {
    return false;
  }

  /**
   * Checks if running on web platform.
   * @returns false, as this is not web
   */
  isWeb(): boolean {
    return false;
  }

  // ... (all other existing methods remain unchanged)
}
