import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, map } from 'rxjs';
import { bilingual } from '../../../shared/i18n/bilingual';
import { ApiConfigService } from '../../../core/services/api-config.service';
import {
  OfferingEntryBootstrapDto, OfferingEntryLineAddedDto,
  AppendOfferingLineRequest, OfferingGivingLineRequest, MemberTypeaheadDto,
  QuickAddMemberRequest,
} from '../models/giving.model';

/**
 * Anonymous API for the mobile offering-entry page. Unlike the other giving
 * services these endpoints require no JWT (the page has no login yet).
 */
@Injectable({ providedIn: 'root' })
export class OfferingEntryApiService {
  private readonly endpoint: string;
  constructor(private http: HttpClient, apiConfig: ApiConfigService) {
    this.endpoint = apiConfig.getApiUrl('offering-entry');
  }

  /** Categories + today's session state, with the bilingual category label computed client-side. */
  bootstrap(date: string): Observable<OfferingEntryBootstrapDto> {
    const params = new HttpParams().set('date', date);
    return this.http.get<OfferingEntryBootstrapDto>(`${this.endpoint}/bootstrap`, { params }).pipe(
      map(dto => ({
        ...dto,
        categories: dto.categories.map(c => ({ ...c, label: bilingual(c.name_en, c.name_zh) })),
      })),
    );
  }

  searchMembers(search: string, take = 10): Observable<MemberTypeaheadDto[]> {
    const params = new HttpParams().set('search', search).set('take', take);
    return this.http.get<MemberTypeaheadDto[]>(`${this.endpoint}/members`, { params });
  }

  appendLine(date: string, line: OfferingGivingLineRequest): Observable<OfferingEntryLineAddedDto> {
    const body: AppendOfferingLineRequest = { date, line };
    return this.http.post<OfferingEntryLineAddedDto>(`${this.endpoint}/lines`, body);
  }

  /** Quick-add a giver not yet on file (created as a Visitor). */
  quickAddMember(request: QuickAddMemberRequest): Observable<MemberTypeaheadDto> {
    return this.http.post<MemberTypeaheadDto>(`${this.endpoint}/members`, request);
  }

  /**
   * Fetch the date's existing proof PDF (so new pages can be merged into it).
   * The server returns 204 No Content when none exists yet — the body is then an
   * empty Blob, which the caller treats as "nothing to merge".
   */
  downloadProof(date: string): Observable<Blob> {
    const params = new HttpParams().set('date', date);
    return this.http.get(`${this.endpoint}/proof`, { params, responseType: 'blob' });
  }

  /** Upload the merged paper-proof PDF (built client-side) for the date's session. */
  uploadProof(date: string, pdf: Blob): Observable<void> {
    const form = new FormData();
    form.append('date', date);
    form.append('file', pdf, 'proof.pdf');
    return this.http.post<void>(`${this.endpoint}/proof`, form);
  }
}
