import { Injectable } from '@angular/core';
import { Client, Account, Databases, ID, Query, Models } from 'appwrite';
import { environment } from '../../environments/environment';
import { Observable, from } from 'rxjs';
import { tap, map } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class AppwriteService {
  private client: Client;
  private account: Account;
  private databases: Databases;
  private readonly localStorageKey = 'appwriteRecords';

  constructor() {
    this.client = new Client()
    .setEndpoint(environment.appwriteEndpoint) // Your Appwrite API endpoint
    .setProject(environment.appwriteProjectId); // Your project ID
    this.account = new Account(this.client);
    this.databases = new Databases(this.client);
  }

  // --- Account Service ---

  get accountService(): Account {
    return this.account;
  }

  async register(email: string, password: string, name: string): Promise<any> {
    return await this.account.create(ID.unique(), email, password, name);
  }

  // --- CRUD Operations for Databases ---


  /**
   * Creates a new document in a specified collection.
   * @param databaseId The ID of the database.
   * @param collectionId The ID of the collection.
   * @param data The data object for the new document.
   * @returns A promise with the created document.
   */
  async createDocument(data: any): Promise<any> {
    try {
      const result = await this.databases.createDocument(
        environment.appwriteDatabaseId,
        environment.appwriteCollectionId,
        ID.unique(),
        data,
      );
      return result;
    } catch (error) {
      console.error('Error creating document:', error);
      throw error;
    }
  }

  /**
   * Retrieves a single document from a collection.
   * @param databaseId The ID of the database.
   * @param collectionId The ID of the collection.
   * @param documentId The ID of the document to retrieve.
   * @returns A promise with the retrieved document.
   */
  async getDocument(documentId: string): Promise<any> {
    try {
      const result = await this.databases.getDocument(
        environment.appwriteDatabaseId,
        environment.appwriteCollectionId,
        documentId,
      );
      return result;
    } catch (error) {
      console.error('Error getting document:', error);
      throw error;
    }
  }

  /**
   * Lists documents from a specified collection with optional queries.
   * @param databaseId The ID of the database.
   * @param collectionId The ID of the collection.
   * @param queries An array of Query objects to filter the results (e.g., [Query.equal('name', 'John')]).
   * @returns A promise with the list of documents.
   */
  public getRecords(queries: string[] = []): Observable<any> {
    //If no Data in localStorage
    return from(
      this.databases.listDocuments(
        environment.appwriteDatabaseId,
        environment.appwriteCollectionId,
        queries,
      ),
    ).pipe(
      map((response: Models.DocumentList<any>) => response.documents),
      tap((documents: any) => {
        this.saveToLocalStorage(documents);
      }),
    );
  }

  // Rest deines Codes bleibt unverändert
  private saveToLocalStorage(data: any): void {
    try {
      localStorage.setItem(this.localStorageKey, JSON.stringify(data));
    } catch (e) {
      console.error('Fehler beim Speichern im LocalStorage', e);
    }
  }

  // Lädt die Daten aus dem LocalStorage und parst sie als JSON
  private loadFromLocalStorage(): any | null {
    try {
      const storedData = localStorage.getItem(this.localStorageKey);
      return storedData ? JSON.parse(storedData) : null;
    } catch (e) {
      console.error('Fehler beim Laden aus LocalStorage', e);
      return null;
    }
  }

  // async listDocuments(
  //   queries: string[] = []
  // ): Promise<any> {
  //   try {
  //     const result = await this.databases.listDocuments(
  //       environment.appwriteDatabaseId,
  //       environment.appwriteCollectionId,
  //       queries
  //     );
  //     return result;
  //   } catch (error) {
  //     console.error('Error listing documents:', error);
  //     throw error;
  //   }
  // }

  /**
   * Updates an existing document in a collection.
   * @param databaseId The ID of the database.
   * @param collectionId The ID of the collection.
   * @param documentId The ID of the document to update.
   * @param data The new data object to merge with the existing document.
   * @returns A promise with the updated document.
   */
  async updateDocument(documentId: string, data: any): Promise<any> {
    try {
      const result = await this.databases.updateDocument(
        environment.appwriteDatabaseId,
        environment.appwriteCollectionId,
        documentId,
        data,
      );
      return result;
    } catch (error) {
      console.error('Error updating document:', error);
      throw error;
    }
  }

  /**
   * Deletes a document from a collection.
   * @param databaseId The ID of the database.
   * @param collectionId The ID of the collection.
   * @param documentId The ID of the document to delete.
   * @returns A promise that resolves upon successful deletion.
   */
  async deleteDocument(documentId: string): Promise<any> {
    try {
      await this.databases.deleteDocument(
        environment.appwriteDatabaseId,
        environment.appwriteCollectionId,
        documentId,
      );
      return { success: true, message: 'Document deleted successfully.' };
    } catch (error) {
      console.error('Error deleting document:', error);
      throw error;
    }
  }
}
