import {
  ImageResult,
  PlatformService,
  PlatformCapabilities,
} from "../PlatformService";
import { Filesystem, Directory } from "@capacitor/filesystem";
import { Camera, CameraResultType, CameraSource } from "@capacitor/camera";
import { logger } from "../../utils/logger";

/**
 * Platform service implementation for Capacitor (mobile) platform.
 * Provides native mobile functionality through Capacitor plugins for:
 * - File system operations
 * - Camera and image picker
 * - Platform-specific features
 */
export class CapacitorPlatformService implements PlatformService {
  /**
   * Gets the capabilities of the Capacitor platform
   * @returns Platform capabilities object
   */
  getCapabilities(): PlatformCapabilities {
    return {
      hasFileSystem: true,
      hasCamera: true,
      isMobile: true,
      isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent),
      hasFileDownload: false,
      needsFileHandlingInstructions: true,
    };
  }

  /**
   * Reads a file from the app's data directory.
   * @param path - Relative path to the file in the app's data directory
   * @returns Promise resolving to the file contents as string
   * @throws Error if file cannot be read or doesn't exist
   */
  async readFile(path: string): Promise<string> {
    const file = await Filesystem.readFile({
      path,
      directory: Directory.Data,
    });
    if (file.data instanceof Blob) {
      return await file.data.text();
    }
    return file.data;
  }

  /**
   * Writes content to a file in the app's data directory.
   * @param path - Relative path where to write the file
   * @param content - Content to write to the file
   * @throws Error if write operation fails
   */
  async writeFile(path: string, content: string): Promise<void> {
    await Filesystem.writeFile({
      path,
      data: content,
      directory: Directory.Data,
    });
  }

  /**
   * Deletes a file from the app's data directory.
   * @param path - Relative path to the file to delete
   * @throws Error if deletion fails or file doesn't exist
   */
  async deleteFile(path: string): Promise<void> {
    await Filesystem.deleteFile({
      path,
      directory: Directory.Data,
    });
  }

  /**
   * Lists files in the specified directory within app's data directory.
   * @param directory - Relative path to the directory to list
   * @returns Promise resolving to array of filenames
   * @throws Error if directory cannot be read or doesn't exist
   */
  async listFiles(directory: string): Promise<string[]> {
    const result = await Filesystem.readdir({
      path: directory,
      directory: Directory.Data,
    });
    return result.files.map((file) =>
      typeof file === "string" ? file : file.name,
    );
  }

  /**
   * Opens the device camera to take a picture.
   * Configures camera for high quality images with editing enabled.
   * @returns Promise resolving to the captured image data
   * @throws Error if camera access fails or user cancels
   */
  async takePicture(): Promise<ImageResult> {
    try {
      const image = await Camera.getPhoto({
        quality: 90,
        allowEditing: true,
        resultType: CameraResultType.Base64,
        source: CameraSource.Camera,
      });

      const blob = await this.processImageData(image.base64String);
      return {
        blob,
        fileName: `photo_${Date.now()}.${image.format || "jpg"}`,
      };
    } catch (error) {
      logger.error("Error taking picture with Capacitor:", error);
      throw new Error("Failed to take picture");
    }
  }

  /**
   * Opens the device photo gallery to pick an existing image.
   * Configures picker for high quality images with editing enabled.
   * @returns Promise resolving to the selected image data
   * @throws Error if gallery access fails or user cancels
   */
  async pickImage(): Promise<ImageResult> {
    try {
      const image = await Camera.getPhoto({
        quality: 90,
        allowEditing: true,
        resultType: CameraResultType.Base64,
        source: CameraSource.Photos,
      });

      const blob = await this.processImageData(image.base64String);
      return {
        blob,
        fileName: `photo_${Date.now()}.${image.format || "jpg"}`,
      };
    } catch (error) {
      logger.error("Error picking image with Capacitor:", error);
      throw new Error("Failed to pick image");
    }
  }

  /**
   * Converts base64 image data to a Blob.
   * @param base64String - Base64 encoded image data
   * @returns Promise resolving to image Blob
   * @throws Error if conversion fails
   */
  private async processImageData(base64String?: string): Promise<Blob> {
    if (!base64String) {
      throw new Error("No image data received");
    }

    // Convert base64 to blob
    const byteCharacters = atob(base64String);
    const byteArrays = [];
    for (let offset = 0; offset < byteCharacters.length; offset += 512) {
      const slice = byteCharacters.slice(offset, offset + 512);
      const byteNumbers = new Array(slice.length);
      for (let i = 0; i < slice.length; i++) {
        byteNumbers[i] = slice.charCodeAt(i);
      }
      const byteArray = new Uint8Array(byteNumbers);
      byteArrays.push(byteArray);
    }
    return new Blob(byteArrays, { type: "image/jpeg" });
  }

  /**
   * Handles deep link URLs for the application.
   * Note: Capacitor handles deep links automatically.
   * @param _url - The deep link URL (unused)
   */
  async handleDeepLink(_url: string): Promise<void> {
    // Capacitor handles deep links automatically
    // This is just a placeholder for the interface
    return Promise.resolve();
  }
}
