import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, from, switchMap } from 'rxjs';
import { ApiConfigService } from '../../../core/services/api-config.service';
import { ImageUtils } from '../../../shared/utilities/image-utils';
import {
  PagedResult, ExpenseListItemDto, ExpenseDto, CreateExpenseRequest, UpdateExpenseRequest,
  RejectExpenseRequest, PayExpenseRequest,
} from '../models/expense.model';

export interface ExpenseQuery {
  page?: number; pageSize?: number; search?: string; ministryId?: number;
  categoryGroupId?: number; status?: string; from?: string; to?: string;
  subCategoryId?: number; statuses?: string;
}

@Injectable({ providedIn: 'root' })
export class ExpenseApiService {
  private readonly endpoint: string;
  constructor(private http: HttpClient, apiConfig: ApiConfigService) {
    this.endpoint = apiConfig.getApiUrl('expenses');
  }
  private toParams(q: Record<string, unknown>): HttpParams {
    let p = new HttpParams();
    for (const [k, v] of Object.entries(q)) if (v !== undefined && v !== null && v !== '') p = p.set(k, String(v));
    return p;
  }
  getPaged(q: ExpenseQuery): Observable<PagedResult<ExpenseListItemDto>> {
    return this.http.get<PagedResult<ExpenseListItemDto>>(this.endpoint, { params: this.toParams(q as Record<string, unknown>) });
  }
  getMine(status?: string, page = 1, pageSize = 50): Observable<PagedResult<ExpenseListItemDto>> {
    return this.http.get<PagedResult<ExpenseListItemDto>>(`${this.endpoint}/mine`, { params: this.toParams({ status, page, pageSize }) });
  }
  getById(id: number): Observable<ExpenseDto> { return this.http.get<ExpenseDto>(`${this.endpoint}/${id}`); }
  create(r: CreateExpenseRequest): Observable<{ id: number }> { return this.http.post<{ id: number }>(this.endpoint, r); }
  update(id: number, r: UpdateExpenseRequest): Observable<void> { return this.http.put<void>(`${this.endpoint}/${id}`, r); }
  delete(id: number): Observable<void> { return this.http.delete<void>(`${this.endpoint}/${id}`); }
  submit(id: number): Observable<void> { return this.http.post<void>(`${this.endpoint}/${id}/submit`, {}); }
  approve(id: number): Observable<void> { return this.http.post<void>(`${this.endpoint}/${id}/approve`, {}); }
  reject(id: number, r: RejectExpenseRequest): Observable<void> { return this.http.post<void>(`${this.endpoint}/${id}/reject`, r); }
  pay(id: number, r: PayExpenseRequest): Observable<void> { return this.http.post<void>(`${this.endpoint}/${id}/pay`, r); }
  uploadReceipt(id: number, file: File): Observable<void> {
    // Resize/re-encode phone photos client-side first — a raw 12MP camera JPEG
    // is several MB and would 413 on mobile. PDFs pass through untouched.
    return from(ImageUtils.compressForUpload(file)).pipe(
      switchMap(prepared => {
        const form = new FormData();
        form.append('file', prepared);
        return this.http.post<void>(`${this.endpoint}/${id}/receipt`, form);
      }),
    );
  }
  /**
   * Fetches the receipt as a Blob via HttpClient so the auth interceptor attaches
   * the JWT. A plain <a href> / window.open on the API URL would be an unauthenticated
   * browser navigation and the API's [Authorize] would reject it with 401.
   */
  downloadReceipt(id: number): Observable<Blob> {
    return this.http.get(`${this.endpoint}/${id}/receipt`, { responseType: 'blob' });
  }
}
