import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { AgentFamilyMember } from '../interfaces/agent';
import { environment } from 'src/environments/environment.development';

const USE_SERVER = true;
const API_BASE = '/api/v1/agent-family-members';

// Interface to match the API response structure
interface AgentFamilyMemberApiResponse {
  id: number;
  agentId: number;
  nom: string;
  statut?: string;
  dateNaissance?: string;
  sexe?: string;
}

@Injectable({ providedIn: 'root' })
export class AgentFamilyMemberService {
  private apiUrl = environment.apiBaseUrl + API_BASE;

  constructor(private http: HttpClient) {}

  // Helper method to get ngrok bypass headers
  private getNgrokHeaders(): Record<string, string> {
    const isNgrok =
      environment.apiBaseUrl.includes('ngrok-free.app') ||
      environment.apiBaseUrl.includes('ngrok.io') ||
      environment.apiBaseUrl.includes('ngrok');
    return isNgrok ? { 'ngrok-skip-browser-warning': 'true' } : {};
  }

  // Transform API response to AgentFamilyMember
  private transformMember(apiMember: AgentFamilyMemberApiResponse): AgentFamilyMember {
    return {
      id: String(apiMember.id),
      agentId: String(apiMember.agentId),
      nom: apiMember.nom,
      statut: apiMember.statut,
      dateNaissance: apiMember.dateNaissance,
      sexe: apiMember.sexe as 'M' | 'F' | undefined,
    };
  }

  // Helper method to convert date string to LocalDateTime format (YYYY-MM-DDTHH:mm:ss)
  private formatDateForApi(dateStr: string | undefined): string | undefined {
    if (!dateStr) return undefined;
    // If already in ISO format with time, return as is
    if (dateStr.includes('T') || dateStr.includes(' ')) {
      return dateStr;
    }
    // If only date (YYYY-MM-DD), add time component
    if (dateStr.match(/^\d{4}-\d{2}-\d{2}$/)) {
      return `${dateStr}T00:00:00`;
    }
    return dateStr;
  }

  // Transform AgentFamilyMember to API payload
  private transformToApiPayload(member: Partial<AgentFamilyMember>): any {
    const payload: any = {};
    if (member.agentId !== undefined) payload.agentId = Number(member.agentId);
    if (member.nom !== undefined) payload.nom = member.nom;
    if (member.statut !== undefined) payload.statut = member.statut;
    if (member.dateNaissance !== undefined) payload.dateNaissance = this.formatDateForApi(member.dateNaissance);
    if (member.sexe !== undefined) payload.sexe = member.sexe;
    return payload;
  }

  // GET /api/v1/agent-family-members/{id} - Get by ID
  getById(id: string): Observable<AgentFamilyMember | undefined> {
    if (USE_SERVER) {
      return this.http
        .get<AgentFamilyMemberApiResponse>(`${this.apiUrl}/${id}`, { headers: this.getNgrokHeaders() })
        .pipe(
          map((apiMember) => this.transformMember(apiMember)),
          catchError((err) => {
            console.error(`Error fetching agent family member ${id}:`, err);
            return of(undefined);
          })
        );
    }
    return of(undefined);
  }

  // GET /api/v1/agent-family-members - List all
  list(): Observable<AgentFamilyMember[]> {
    if (USE_SERVER) {
      return this.http
        .get<AgentFamilyMemberApiResponse[]>(this.apiUrl, { headers: this.getNgrokHeaders() })
        .pipe(
          map((list) => list.map((apiMember) => this.transformMember(apiMember))),
          catchError((err) => {
            console.error('Error fetching agent family members:', err);
            return of([]);
          })
        );
    }
    return of([]);
  }

  // POST /api/v1/agent-family-members - Create
  create(payload: Omit<AgentFamilyMember, 'id'>): Observable<AgentFamilyMember> {
    if (USE_SERVER) {
      const apiPayload = this.transformToApiPayload(payload);
      return this.http
        .post<AgentFamilyMemberApiResponse>(this.apiUrl, apiPayload, { headers: this.getNgrokHeaders() })
        .pipe(
          map((apiMember) => this.transformMember(apiMember)),
          catchError((err) => {
            console.error('Error creating agent family member:', err);
            throw err;
          })
        );
    }
    throw new Error('Server mode is required');
  }

  // PUT /api/v1/agent-family-members/{id} - Update
  update(id: string, payload: Partial<AgentFamilyMember>): Observable<AgentFamilyMember | undefined> {
    if (USE_SERVER) {
      const apiPayload = this.transformToApiPayload(payload);
      return this.http
        .put<AgentFamilyMemberApiResponse>(`${this.apiUrl}/${id}`, apiPayload, { headers: this.getNgrokHeaders() })
        .pipe(
          map((apiMember) => this.transformMember(apiMember)),
          catchError((err) => {
            console.error(`Error updating agent family member ${id}:`, err);
            return of(undefined);
          })
        );
    }
    return of(undefined);
  }

  // DELETE /api/v1/agent-family-members/{id} - Delete
  delete(id: string): Observable<boolean> {
    if (USE_SERVER) {
      return this.http
        .delete<void>(`${this.apiUrl}/${id}`, { headers: this.getNgrokHeaders() })
        .pipe(
          map(() => true),
          catchError((err) => {
            console.error(`Error deleting agent family member ${id}:`, err);
            return of(false);
          })
        );
    }
    return of(false);
  }

  // GET /api/v1/agent-family-members/statut/{statut} - List by statut
  getByStatut(statut: string): Observable<AgentFamilyMember[]> {
    if (USE_SERVER) {
      return this.http
        .get<AgentFamilyMemberApiResponse[]>(`${this.apiUrl}/statut/${statut}`, { headers: this.getNgrokHeaders() })
        .pipe(
          map((list) => list.map((apiMember) => this.transformMember(apiMember))),
          catchError((err) => {
            console.error(`Error fetching agent family members by statut ${statut}:`, err);
            return of([]);
          })
        );
    }
    return of([]);
  }

  // GET /api/v1/agent-family-members/sexe/{sexe} - List by sexe
  getBySexe(sexe: 'M' | 'F'): Observable<AgentFamilyMember[]> {
    if (USE_SERVER) {
      return this.http
        .get<AgentFamilyMemberApiResponse[]>(`${this.apiUrl}/sexe/${sexe}`, { headers: this.getNgrokHeaders() })
        .pipe(
          map((list) => list.map((apiMember) => this.transformMember(apiMember))),
          catchError((err) => {
            console.error(`Error fetching agent family members by sexe ${sexe}:`, err);
            return of([]);
          })
        );
    }
    return of([]);
  }

  // GET /api/v1/agent-family-members/search - Search by keyword
  search(query: string): Observable<AgentFamilyMember[]> {
    if (USE_SERVER) {
      return this.http
        .get<AgentFamilyMemberApiResponse[]>(`${this.apiUrl}/search`, {
          params: { q: query.trim() },
          headers: this.getNgrokHeaders(),
        })
        .pipe(
          map((list) => list.map((apiMember) => this.transformMember(apiMember))),
          catchError((err) => {
            console.error(`Error searching agent family members with query ${query}:`, err);
            return of([]);
          })
        );
    }
    return of([]);
  }

  // GET /api/v1/agent-family-members/nom/{nom} - List by nom
  getByNom(nom: string): Observable<AgentFamilyMember[]> {
    if (USE_SERVER) {
      return this.http
        .get<AgentFamilyMemberApiResponse[]>(`${this.apiUrl}/nom/${nom}`, { headers: this.getNgrokHeaders() })
        .pipe(
          map((list) => list.map((apiMember) => this.transformMember(apiMember))),
          catchError((err) => {
            console.error(`Error fetching agent family members by nom ${nom}:`, err);
            return of([]);
          })
        );
    }
    return of([]);
  }

  // Get family members by agentId (filter from list)
  getByAgentId(agentId: string): Observable<AgentFamilyMember[]> {
    if (USE_SERVER) {
      return this.list().pipe(
        map((list) => list.filter((member) => member.agentId === agentId)),
        catchError((err) => {
          console.error(`Error fetching agent family members by agentId ${agentId}:`, err);
          return of([]);
        })
      );
    }
    return of([]);
  }
}

