import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, forkJoin, of } from 'rxjs';
import { switchMap, map } from 'rxjs/operators';
import { environment } from '../../../environments/environment';
import { ApiResponse, PaginatedResponse } from '../models/api.model';
import { Partner, CreatePartner, UpdatePartner, PartnerContact, PartnerAddress } from '../models/partner.model';

@Injectable({ providedIn: 'root' })
export class PartnerService {
  private http = inject(HttpClient);
  private baseUrl = `${environment.apiUrl}/core/partners`;
  private contactsUrl = `${environment.apiUrl}/core/contacts`;
  private addressesUrl = `${environment.apiUrl}/core/addresses`;

  list(page?: number, perPage?: number): Observable<PaginatedResponse<Partner>> {
    const params: any = {};
    if (page) params.page = page;
    if (perPage) params.per_page = perPage;
    return this.http.get<PaginatedResponse<Partner>>(this.baseUrl, { params });
  }

  searchForDropdown(query: string, filters?: Record<string, string>): Observable<PaginatedResponse<Partner>> {
    const params: any = { search: query };
    if (filters) Object.assign(params, filters);
    return this.http.get<PaginatedResponse<Partner>>(this.baseUrl, { params });
  }

  listAll(): Observable<PaginatedResponse<Partner>> {
    return this.list(1, 200).pipe(
      switchMap((firstPage) => {
        const lastPage = firstPage.meta.last_page;
        if (lastPage <= 1) return of(firstPage);
        const requests: Observable<PaginatedResponse<Partner>>[] = [];
        for (let p = 2; p <= lastPage; p++) requests.push(this.list(p, 200));
        return forkJoin(requests).pipe(
          map((responses) => {
            const allData = [...firstPage.data, ...responses.flatMap((r) => r.data)];
            return { data: allData, links: firstPage.links, meta: { ...firstPage.meta, current_page: 1, last_page: 1, per_page: allData.length, to: allData.length, total: allData.length } } as PaginatedResponse<Partner>;
          })
        );
      })
    );
  }

  getById(id: number): Observable<ApiResponse<Partner>> {
    return this.http.get<ApiResponse<Partner>>(`${this.baseUrl}/${id}`);
  }

  create(data: CreatePartner): Observable<ApiResponse<Partner>> {
    return this.http.post<ApiResponse<Partner>>(this.baseUrl, data);
  }

  update(id: number, data: UpdatePartner): Observable<ApiResponse<Partner>> {
    return this.http.put<ApiResponse<Partner>>(`${this.baseUrl}/${id}`, data);
  }

  delete(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`);
  }

  // Contacts
  listContacts(partnerId: number): Observable<ApiResponse<PartnerContact[]>> {
    return this.http.get<ApiResponse<PartnerContact[]>>(`${this.baseUrl}/${partnerId}/contacts`);
  }

  createContact(partnerId: number, data: any): Observable<ApiResponse<PartnerContact>> {
    return this.http.post<ApiResponse<PartnerContact>>(`${this.baseUrl}/${partnerId}/contacts`, data);
  }

  updateContact(contactId: number, data: any): Observable<ApiResponse<PartnerContact>> {
    return this.http.put<ApiResponse<PartnerContact>>(`${this.contactsUrl}/${contactId}`, data);
  }

  deleteContact(contactId: number): Observable<any> {
    return this.http.delete(`${this.contactsUrl}/${contactId}`);
  }

  // Addresses
  listAddresses(partnerId: number): Observable<ApiResponse<PartnerAddress[]>> {
    return this.http.get<ApiResponse<PartnerAddress[]>>(`${this.baseUrl}/${partnerId}/addresses`);
  }

  createAddress(partnerId: number, data: any): Observable<ApiResponse<PartnerAddress>> {
    return this.http.post<ApiResponse<PartnerAddress>>(`${this.baseUrl}/${partnerId}/addresses`, data);
  }

  updateAddress(addressId: number, data: any): Observable<ApiResponse<PartnerAddress>> {
    return this.http.put<ApiResponse<PartnerAddress>>(`${this.addressesUrl}/${addressId}`, data);
  }

  deleteAddress(addressId: number): Observable<any> {
    return this.http.delete(`${this.addressesUrl}/${addressId}`);
  }

  // Freeze / Unfreeze
  freeze(partnerId: number): Observable<ApiResponse<Partner>> {
    return this.http.post<ApiResponse<Partner>>(`${this.baseUrl}/${partnerId}/freeze`, {});
  }

  unfreeze(partnerId: number): Observable<ApiResponse<Partner>> {
    return this.http.post<ApiResponse<Partner>>(`${this.baseUrl}/${partnerId}/unfreeze`, {});
  }

  // Debt Changes
  listDebtChanges(partnerId: number): Observable<{ data: any[] }> {
    return this.http.get<{ data: any[] }>(`${this.baseUrl}/${partnerId}/debt-changes`);
  }

  createDebtChange(data: { business_partner_id: number; amount: number; type: string; reason?: string; reason_ar?: string; date?: string; reference?: string }): Observable<ApiResponse<any>> {
    return this.http.post<ApiResponse<any>>(`${environment.apiUrl}/core/debt-changes`, data);
  }
}
