import { HttpClient, HttpHeaders, HttpParams } from "@angular/common/http";
import { Inject, Injectable, LOCALE_ID } from "@angular/core";
import { Observable } from "rxjs";
import { map, tap, timeout } from "rxjs/operators";
import { Projects } from "src/app/models/project";

import { DocumentStore } from "src/app/stores/documents.store";

import { ProjectsStore } from "src/app/stores/projects.store";

import { UserStore } from "src/app/stores/user.store";
import { environment } from "../../environments/environment";
import { StorageService } from "../core/services/storage.service";
import { ApiRouterService } from "../core/services/api-router.service";

@Injectable({
  providedIn: "root",
})
export class GlobalService {
  private userId = "";
  private sessionsId = "";

  constructor(
    private http: HttpClient,
    public projectStore: ProjectsStore,
    private userStore: UserStore,
    public storage: StorageService,
    @Inject(LOCALE_ID) private locale: string,
    public documentStore: DocumentStore,
    private apiRouterService: ApiRouterService
  ) {
    this.userStore
      .select("user")
      .pipe(
        tap((res: any) => {
          if (res.accessKey) {
            this.userId = res.userInfo.userId;
            this.sessionsId = res.accessKey;
          }
        })
      )
      .subscribe();
  }

  /**
   * Nouvelle méthode avec pagination et filtres
   */
  public getPagedData(
    domaine: string, 
    modulename: string, 
    page: number = 1, 
    size: number = 100,
    filters: any = {},
    search: string = ''
  ): Promise<any> {
    console.log("getPagedData:", { domaine, modulename, page, size, filters, search });
    
    const apiConfig = this.apiRouterService.getApiConfig(domaine, modulename);
    const headers = this.createHeaders(apiConfig.apiKey);
    
    const isChaps = apiConfig.baseUrl === environment.API_URL;
    let url = `${apiConfig.baseUrl}${isChaps ? 'v1/' : ''}admin/${modulename}`;

    // Construction des paramètres HTTP
    let httpParams = new HttpParams()
      .set('page', page.toString())
      .set('size', size.toString());
    
    if (search && search.trim()) {
      httpParams = httpParams.set('search', search.trim());
    }
    
    // Ajout des filtres
    if (filters && typeof filters === 'object') {
      Object.keys(filters).forEach(key => {
        if (filters[key] !== null && filters[key] !== undefined && filters[key] !== '') {
          httpParams = httpParams.set(`filters[${key}]`, filters[key]);
        }
      });
    }
    
    console.log("getPagedData URL:", url);
    console.log("getPagedData Params:", httpParams.toString());
    console.log("getPagedData Headers:", headers);
    
    return this.http.get<any>(url, { headers, params: httpParams })
      .toPromise()
      .then(response => {
        console.log("getPagedData Success:", response);
        return response;
      })
      .catch(error => {
        console.error("getPagedData Error:", error);
        console.error("Error details:", {
          status: error.status,
          statusText: error.statusText,
          message: error.message,
          url: url,
          params: httpParams.toString()
        });
        throw error;
      });
  }

  public getAll(domaine: string, modulename: string): Promise<any> {
    console.log("getAll : ", domaine, modulename);
    console.log("Environment:", {
      production: environment.production,
      DATA_URL: environment.DATA_URL,
      API_URL: environment.API_URL
    });
    
    const apiKey =
      domaine == "parametre"
        ? environment.X_APY_KEY
        : environment.DATA_APY_KEY;
    const headers = this.createHeaders(apiKey);

    let url = `${environment.DATA_URL}admin/${modulename}`;
    if (domaine == "parametre") {
      url = `${environment.API_URL}v1/admin/${modulename}`;
    }

    console.log("getAll URL:", url);
    console.log("getAll Headers:", headers);

    return this.http.get<any>(`${url}`, { headers })
      .toPromise()
      .then(response => {
        console.log("getAll Success:", response);
        return response;
      })
      .catch(error => {
        console.error("getAll Error:", error);
        console.error("Error details:", {
          status: error.status,
          statusText: error.statusText,
          message: error.message,
          url: url
        });
        throw error;
      });
  }
  public getAllElements(url: string): Promise<any> {
    const headers = this.createHeaders(environment.X_APY_KEY);
    return this.http
      .get<any>(`${environment.API_URL}${url}`, { headers })
      .toPromise();
  }

  public getProjects(modulename: string, projects: any) {
    this.projectStore
      .select("projects")
      .pipe(
        tap((res: any) => {
          if (!res[modulename]) {
            let data = { ...res, ...{ [modulename]: projects.records } };
            this.projectStore.setProjects(data);
          }
        })
      )
      .subscribe();
  }
  public getDetails(
    domaine: string,
    modulename: string,
    id: string
  ): Promise<any> {
    const apiKey =
      domaine == "parametre"
        ? environment.X_APY_KEY
        : environment.DATA_APY_KEY;
    const headers = this.createHeaders(apiKey);

    let url = `${environment.DATA_URL}admin/${modulename}`;
    if (domaine == "parametre") {
      url = `${environment.API_URL}v1/admin/${modulename}`;
    }
    return this.http.get<any>(`${url}/${id}`, { headers }).toPromise();
  }
  async addObject(data: any, modulename: any): Promise<any> {
    const headers = this.createHeaders();
    return this.http
      .post<any>(
        `${environment.DATA_URL}admin/${modulename}`,
        { element: data },
        { headers }
      )
      .toPromise();
  }
  async importData(data: FormData): Promise<any> {
    const headers = this.createHeaders(environment.X_APY_KEY);
    return this.http
      .post<any>(`${environment.API_URL}v1/admin/import-file`, data, { headers })
      .toPromise();
  }
  async updateObject(
    data: any,
    recordId: any,
    modulename: string
  ): Promise<any> {
    const headers = this.createHeaders();
    return this.http
      .put<any>(
        `${environment.DATA_URL}admin/${modulename}/${recordId}`,
        {
          element: data,
          setup: environment.SETUP,
        },
        { headers }
      )
      .toPromise();
  }

  public setDetails(projects: any, id: string) {
    this.projectStore
      .select("details")
      .pipe(
        tap((res: any) => {
          if (res[id] == undefined) {
            let data = { ...res, ...{ [id]: projects.record } };
            this.projectStore.setDetails(data);
          }
        })
      )
      .subscribe();
  }
  async getListViewlements(modulename: string): Promise<any[]> {
    const headers = this.createHeaders(environment.X_APY_KEY);
    return this.http
      .get<any>(`${environment.API_URL}v1/metadata/${modulename}`, { headers })
      .toPromise();
  }

  public getIdSelected(data: []) {
    const response = data.map((res: Projects) => {
      return res.projetsid;
    });

    return response;
  }

  public filtreTable(projects: any): void {
    // Méthode vide, à implémenter si nécessaire
  }

  // recursive function
  public removeEmpty(obj: any): any {
    return Object.entries(obj)
      .filter(([_, v]) => v !== "")
      .reduce(
        (acc, [k, v]) => ({
          ...acc,
          [k]: v === Object(v) ? this.removeEmpty(v) : v,
        }),
        {}
      );
  }

  private formatRetourProject(data: any) {
    const response =
      data &&
      data.length > 0 &&
      data.map((res: any) => {
        return {
          ...res,
          "Volume MWhc": parseFloat(res["Volume MWhc"]),
          "Valeur de la position": parseFloat(res["Valeur de la position"]),
          "Volume MWhc estime": parseFloat(res["Volume MWhc estime"]),
        };
      });
    return response ? response : [];
  }
  // Méthodes ajoutées pour corriger les erreurs de compilation
  public updateDepots(projectId: string, depotId: string): Observable<any> {
    const headers = this.createHeaders();
    return this.http
      .put<any>(
        `${environment.DATA_URL}admin/projets/${projectId}/depot`,
        { depotId },
        { headers }
      )
      .pipe(map((response: any) => response));
  }
  /**
   * Exécute une action sur un module spécifique
   */
  public async executeAction(
    moduleName: string, 
    recordId: string, 
    action: string, 
    data: any = {}
  ): Promise<any> {
    console.log(`📡 Appel API executeAction:`, { moduleName, recordId, action, data });
    
    const apiConfig = this.apiRouterService.getApiConfig('data', moduleName);
    const headers = this.createHeaders(apiConfig.apiKey);
    
    const url = `${apiConfig.baseUrl}admin/${moduleName}/execute`;
    
    const payload = {
      recordId: recordId,
      action: action,
      data: data
    };
    
    console.log(`📤 POST ${url}`, payload);
    
    return this.http.post<any>(url, payload, { headers })
      .toPromise()
      .then(response => {
        console.log(`✅ executeAction Success:`, response);
        return response;
      })
      .catch(error => {
        console.error(`❌ executeAction Error:`, error);
        console.error('Error details:', {
          status: error.status,
          statusText: error.statusText,
          message: error.message,
          url: url,
          payload: payload
        });
        throw error;
      });
  }

  // Méthode pour centraliser la création des headers HTTP
  private createHeaders(
    apiKey: string = environment.DATA_APY_KEY
  ): HttpHeaders {
    const tokenData = this.storage.getItem("__token");
    
    if (!tokenData) {
      console.error("No token found in localStorage");
      throw new Error("Token manquant - veuillez vous reconnecter");
    }
    
    let token;
    try {
      token = JSON.parse(tokenData);
    } catch (error) {
      console.error("Error parsing token:", error);
      throw new Error("Token invalide - veuillez vous reconnecter");
    }
    
    if (!token.token) {
      console.error("Token object missing token property:", token);
      throw new Error("Token invalide - veuillez vous reconnecter");
    }
    
    console.log("Creating headers with:", {
      hasToken: !!token.token,
      apiKey: apiKey.substring(0, 10) + "...",
      tokenLength: token.token.length
    });
    
    return new HttpHeaders({
      "Content-Type": "application/json",
      Authorization: `Bearer ${token.token}`,
      "X-API-KEY": apiKey,
    });
  }
}
