import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpParams } 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 { AllocationRule, CreateAllocationRule, UpdateAllocationRule } from '../models/allocation-rule.model';

@Injectable({ providedIn: 'root' })
export class AllocationRuleService {
  private http = inject(HttpClient);
  private baseUrl = `${environment.apiUrl}/accounting/allocation-rules`;

  list(page = 1, perPage = 100): Observable<PaginatedResponse<AllocationRule>> {
    const params = new HttpParams().set('page', page).set('per_page', perPage);
    return this.http.get<PaginatedResponse<AllocationRule>>(this.baseUrl, { params });
  }

  listAll(): Observable<PaginatedResponse<AllocationRule>> {
    return this.list(1, 200).pipe(
      switchMap((firstPage) => {
        const lastPage = firstPage.meta.last_page;
        if (lastPage <= 1) return of(firstPage);
        const requests: Observable<PaginatedResponse<AllocationRule>>[] = [];
        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<AllocationRule>;
          })
        );
      })
    );
  }

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

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

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

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

  simulate(id: number, period_start: string, period_end: string): Observable<any> {
    return this.http.post(`${this.baseUrl}/${id}/simulate`, { period_start, period_end });
  }

  execute(id: number, period_start: string, period_end: string): Observable<any> {
    return this.http.post(`${this.baseUrl}/${id}/execute`, { period_start, period_end });
  }
}
