/**
 * Form 16 API – credit notes and (later) submissions.
 * Uses apiClient for JSON; uses fetch for FormData (so browser sets multipart boundary).
 */

import apiClient from './authApi';
import { TokenManager } from '@/utils/tokenManager';

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000/api/v1';

/**
 * REform16 pattern: authenticated request; do NOT set Content-Type for FormData (browser sets multipart/form-data + boundary).
 */
async function fetchWithAuth(url: string, options: RequestInit = {}): Promise<{ data?: unknown; message?: string; success?: boolean }> {
  const token = TokenManager.getAccessToken();
  const headers: HeadersInit = {
    ...(options.headers || {}),
  };
  if (!(options.body instanceof FormData)) {
    (headers as Record<string, string>)['Content-Type'] = 'application/json';
  }
  if (token) {
    (headers as Record<string, string>)['Authorization'] = `Bearer ${token}`;
  }
  const response = await fetch(`${API_BASE_URL}${url}`, {
    ...options,
    headers,
    credentials: 'include',
  });
  const contentType = response.headers.get('content-type');
  const isJson = contentType?.includes('application/json');
  const data = isJson ? await response.json() : { message: await response.text() || 'Request failed' };
  if (!response.ok) {
    const err = new Error((data as { message?: string }).message || `Request failed ${response.status}`) as Error & { response?: { status: number; data?: unknown } };
    err.response = { status: response.status, data };
    throw err;
  }
  return data as { data?: unknown; message?: string; success?: boolean };
}

export interface Form16CreditNoteSubmission {
  requestId: string;
  form16aNumber: string | null;
  financialYear: string | null;
  quarter: string | null;
  status: string | null;
}

export interface Form16CreditNoteItem {
  id: string;
  creditNoteNumber: string | null;
  sapDocumentNumber: string | null;
  /** True when SAP response CSV is ingested and downloadable */
  sapResponseAvailable?: boolean;
  amount: number | null;
  issueDate: string | null;
  financialYear: string | null;
  quarter: string | null;
  status: string | null;
  remarks: string | null;
  submission: Form16CreditNoteSubmission | null;
  /** RE view: dealer code (when listing all credit notes) */
  dealerCode?: string | null;
  dealerName?: string | null;
}

export async function getCreditNoteDownloadUrl(id: number): Promise<string> {
  const fallbackCsvApiUrl = `/api/v1/form16/credit-notes/${id}/sap-response/csv`;
  const { data } = await apiClient.get<{ data?: { url?: string }; url?: string }>(`/form16/credit-notes/${id}/download`);
  const payload = data?.data ?? data;
  const url = payload?.url;
  // Hard-stop on legacy local-file links; View/Download must use API-backed DB data.
  if (!url || String(url).startsWith('/uploads/')) return fallbackCsvApiUrl;
  return String(url);
}

export interface ListCreditNotesSummary {
  totalCreditNotes: number;
  totalAmount: number;
  activeDealersCount: number;
}

export interface ListCreditNotesResponse {
  creditNotes: Form16CreditNoteItem[];
  total: number;
  summary?: ListCreditNotesSummary;
}

export interface ListCreditNotesParams {
  financialYear?: string;
  quarter?: string;
}

// ---------- Debit notes (RE only) ----------

export interface Form16DebitNoteListItem {
  id: number;
  debitNoteNumber: string | null;
  sapDocumentNumber?: string | null;
  sapResponseAvailable?: boolean;
  amount: number | null;
  issueDate: string | null;
  status: string | null;
  financialYear?: string | null;
  quarter?: string | null;
  creditNoteNumber?: string | null;
  dealerCode?: string | null;
  dealerName?: string | null;
  form16aNumber?: string | null;
}

export interface ListDebitNotesSummary {
  totalDebitNotes: number;
  totalAmount: number;
  impactedDealersCount?: number;
}

export interface ListDebitNotesResponse {
  debitNotes: Form16DebitNoteListItem[];
  total: number;
  summary?: ListDebitNotesSummary;
}

export interface ListDebitNotesParams {
  financialYear?: string;
  quarter?: string;
}

export interface Form16SapResponseRecord {
  fileName: string | null;
  trnsUniqNo: string | null;
  tdsTransId: string | null;
  sapDocumentNumber: string | null;
  msgTyp: string | null;
  message: string | null;
  docDate: string | null;
  tdsAmt: string | null;
  storageUrl: string | null;
  createdAt: string | null;
  updatedAt: string | null;
}

export interface Form16SapResponsePayload {
  sapResponse: Form16SapResponseRecord;
  url?: string | null;
}

export interface Form16Permissions {
  canViewForm16Submission: boolean;
  canView26AS: boolean;
}

/**
 * Get Form 16 permissions for the current user (API-driven from admin config).
 * Use to show/hide Form 16 menu, 26AS, and submission data in the UI.
 */
export async function getForm16Permissions(): Promise<Form16Permissions> {
  const res = await apiClient.get<{ data: Form16Permissions }>('/form16/permissions');
  const data = res.data?.data ?? res.data;
  return {
    canViewForm16Submission: !!data?.canViewForm16Submission,
    canView26AS: !!data?.canView26AS,
  };
}

/**
 * List credit notes for the authenticated dealer (resolved by backend from user email).
 */
export async function listCreditNotes(params?: ListCreditNotesParams): Promise<ListCreditNotesResponse> {
  const searchParams = new URLSearchParams();
  if (params?.financialYear) searchParams.set('financialYear', params.financialYear);
  if (params?.quarter) searchParams.set('quarter', params.quarter);
  const query = searchParams.toString();
  const url = query ? `/form16/credit-notes?${query}` : '/form16/credit-notes';
  const { data } = await apiClient.get<{ data?: ListCreditNotesResponse; creditNotes?: Form16CreditNoteItem[]; total?: number; summary?: ListCreditNotesSummary }>(url);
  const payload = data?.data ?? data;
  return {
    creditNotes: payload?.creditNotes ?? [],
    total: payload?.total ?? 0,
    summary: payload?.summary,
  };
}

/**
 * RE only. List debit notes.
 */
export async function listDebitNotes(params?: ListDebitNotesParams): Promise<ListDebitNotesResponse> {
  const searchParams = new URLSearchParams();
  if (params?.financialYear) searchParams.set('financialYear', params.financialYear);
  if (params?.quarter) searchParams.set('quarter', params.quarter);
  const query = searchParams.toString();
  const url = query ? `/form16/debit-notes?${query}` : '/form16/debit-notes';
  const { data } = await apiClient.get<{ data?: ListDebitNotesResponse; debitNotes?: Form16DebitNoteListItem[]; total?: number; summary?: ListDebitNotesSummary }>(url);
  const payload = data?.data ?? data;
  return {
    debitNotes: payload?.debitNotes ?? [],
    total: payload?.total ?? 0,
    summary: payload?.summary,
  };
}

export async function getDebitNoteSapResponseUrl(id: number): Promise<string> {
  const fallbackCsvApiUrl = `/api/v1/form16/debit-notes/${id}/sap-response/csv`;
  const { data } = await apiClient.get<{ data?: { url?: string }; url?: string }>(`/form16/debit-notes/${id}/sap-response`);
  const payload = data?.data ?? data;
  const url = payload?.url;
  if (!url || String(url).startsWith('/uploads/')) return fallbackCsvApiUrl;
  return String(url);
}

export async function getDebitNoteSapResponse(id: number): Promise<Form16SapResponsePayload> {
  const { data } = await apiClient.get<{ data?: Form16SapResponsePayload } | Form16SapResponsePayload>(`/form16/debit-notes/${id}/sap-response`);
  const payload = (data && typeof data === 'object' && 'data' in data ? data.data : data) as Form16SapResponsePayload | undefined;
  if (!payload?.sapResponse) throw new Error('SAP response not available');
  return {
    ...payload,
    // Force API-backed CSV endpoint to avoid any /uploads path leakage.
    url: `/api/v1/form16/debit-notes/${id}/sap-response/csv`,
  };
}

export async function getCreditNoteSapResponse(id: number): Promise<Form16SapResponsePayload> {
  const { data } = await apiClient.get<{ data?: Form16SapResponsePayload } | Form16SapResponsePayload>(`/form16/credit-notes/${id}/sap-response`);
  const payload = (data && typeof data === 'object' && 'data' in data ? data.data : data) as Form16SapResponsePayload | undefined;
  if (!payload?.sapResponse) throw new Error('SAP response not available');
  return {
    ...payload,
    // Force API-backed CSV endpoint to avoid any /uploads path leakage.
    url: `/api/v1/form16/credit-notes/${id}/sap-response/csv`,
  };
}

/** Get credit note linked to a Form 16 request (for workflow tab). */
export async function getCreditNoteByRequestId(requestId: string): Promise<Form16CreditNoteItem | null> {
  const { data } = await apiClient.get<{ data?: { creditNote?: Form16CreditNoteItem | null }; creditNote?: Form16CreditNoteItem | null }>(`/form16/requests/${encodeURIComponent(requestId)}/credit-note`);
  const payload = data?.data ?? data;
  return payload?.creditNote ?? null;
}

/** RE only. Cancel Form 16 submission and mark workflow rejected. */
export async function cancelForm16Submission(requestId: string): Promise<void> {
  await apiClient.post(`/form16/requests/${encodeURIComponent(requestId)}/cancel-submission`);
}

/** RE only. Mark Form 16 submission as resubmission needed. */
export async function setForm16ResubmissionNeeded(requestId: string): Promise<void> {
  await apiClient.post(`/form16/requests/${encodeURIComponent(requestId)}/resubmission-needed`);
}

/** Get a single credit note by id with dealer info and dealer transaction history. */
export interface CreditNoteDetailResponse {
  creditNote: Form16CreditNoteItem & { submission?: { submittedDate?: string | null } };
  dealerName: string;
  dealerEmail: string;
  dealerContact: string;
  /** Present when a debit note was issued for this credit note */
  debitNote?: Form16DebitNoteItem | null;
  dealerCreditNotes: Array<{
    id: number;
    creditNoteNumber: string | null;
    amount: number | null;
    issueDate: string | null;
    status: string | null;
    form16aNumber?: string | null;
    submittedDate?: string | null;
  }>;
}

export async function getCreditNoteById(id: number): Promise<CreditNoteDetailResponse> {
  const { data } = await apiClient.get<{ data?: CreditNoteDetailResponse } | CreditNoteDetailResponse>(`/form16/credit-notes/${id}`);
  const payload = (data && typeof data === 'object' && 'data' in data ? data.data : data) as CreditNoteDetailResponse | undefined;
  if (!payload?.creditNote) throw new Error('Credit note not found');
  return payload;
}

// ---------- Form 16 SAP simulation (replace with real SAP when integrating) ----------

/** Dealer details for SAP credit note simulation */
export interface SapCreditNoteDealerDetails {
  dealerCode: string;
  dealerName?: string | null;
  dealerEmail?: string | null;
  dealerContact?: string | null;
}

/** Simulated SAP credit note response (JSON from SAP) */
export interface SapCreditNoteResponse {
  success: boolean;
  creditNoteNumber: string;
  sapDocumentNumber: string;
  amount: number;
  issueDate: string;
  financialYear?: string;
  quarter?: string;
  status: string;
  message?: string;
}

/** Dealer info for SAP debit note simulation */
export interface SapDebitNoteDealerInfo {
  dealerCode: string;
  dealerName?: string | null;
  dealerEmail?: string | null;
  dealerContact?: string | null;
}

/** Simulated SAP debit note response (JSON from SAP) */
export interface SapDebitNoteResponse {
  success: boolean;
  debitNoteNumber: string;
  sapDocumentNumber: string;
  amount: number;
  issueDate: string;
  status: string;
  creditNoteNumber: string;
  message?: string;
}

/** Simulate SAP credit note generation (Form 16). Returns simulated SAP JSON. */
export async function sapSimulateCreditNote(
  dealerDetails: SapCreditNoteDealerDetails,
  amount: number
): Promise<SapCreditNoteResponse> {
  const { data } = await apiClient.post<{ data?: SapCreditNoteResponse } | SapCreditNoteResponse>(
    '/form16/sap-simulate/credit-note',
    { dealerDetails, amount }
  );
  const payload = (data && typeof data === 'object' && 'data' in data ? data.data : data) as SapCreditNoteResponse | undefined;
  if (!payload?.creditNoteNumber) throw new Error('Simulated credit note not returned');
  return payload;
}

/** Simulate SAP debit note generation (Form 16). Returns simulated SAP JSON. */
export async function sapSimulateDebitNote(params: {
  dealerCode: string;
  dealerInfo?: SapDebitNoteDealerInfo;
  creditNoteNumber: string;
  amount: number;
}): Promise<SapDebitNoteResponse> {
  const { data } = await apiClient.post<{ data?: SapDebitNoteResponse } | SapDebitNoteResponse>(
    '/form16/sap-simulate/debit-note',
    params
  );
  const payload = (data && typeof data === 'object' && 'data' in data ? data.data : data) as SapDebitNoteResponse | undefined;
  if (!payload?.debitNoteNumber) throw new Error('Simulated debit note not returned');
  return payload;
}

/** Debit note item (from generate-debit-note or credit note detail). */
export interface Form16DebitNoteItem {
  id: number;
  debitNoteNumber: string | null;
  sapDocumentNumber?: string | null;
  amount: number | null;
  issueDate: string | null;
  status: string | null;
  reason?: string | null;
}

/** RE only. Generate debit note for a credit note (Form 16). Calls SAP simulation then saves. */
export async function generateForm16DebitNote(
  creditNoteId: number,
  amount: number
): Promise<{ debitNote: Form16DebitNoteItem; creditNote: Form16CreditNoteItem }> {
  const { data } = await apiClient.post<{
    data?: { debitNote?: Form16DebitNoteItem; creditNote?: Form16CreditNoteItem };
    debitNote?: Form16DebitNoteItem;
    creditNote?: Form16CreditNoteItem;
  }>(`/form16/credit-notes/${creditNoteId}/generate-debit-note`, { amount });
  const payload = data?.data ?? data;
  const debitNote = payload?.debitNote;
  const creditNote = payload?.creditNote;
  if (!debitNote) throw new Error('Debit note not returned');
  return { debitNote, creditNote: creditNote! };
}

/** Extracted Form 16A data from OCR (Gemini or regex fallback) */
export interface Form16AExtractedData {
  nameAndAddressOfDeductor?: string | null;
  deductorName?: string | null;
  deductorAddress?: string | null;
  deductorPhone?: string | null;
  deductorEmail?: string | null;
  totalAmountPaid?: number | null;
  totalTaxDeducted?: number | null;
  totalTdsDeposited?: number | null;
  tanOfDeductor?: string | null;
  natureOfPayment?: string | null;
  transactionDate?: string | null;
  statusOfMatchingOltas?: string | null;
  dateOfBooking?: string | null;
  assessmentYear?: string | null;
  quarter?: string | null;
  form16aNumber?: string | null;
  financialYear?: string | null;
  certificateDate?: string | null;
  tanNumber?: string | null;
  tdsAmount?: number | null;
  totalAmount?: number | null;
}

export interface ExtractOcrResponse {
  extractedData: Form16AExtractedData;
  ocrProvider?: string;
}

/**
 * Extract Form 16A data from PDF – exact REform16: FormData with 'document', fetchWithAuth (no Content-Type for FormData).
 */
export async function extractOcr(file: File): Promise<ExtractOcrResponse> {
  const formData = new FormData();
  formData.append('document', file);
  const result = await fetchWithAuth('/form16/extract', {
    method: 'POST',
    body: formData,
  });
  const raw = result as { data?: { extractedData?: Form16AExtractedData; ocrProvider?: string }; extractedData?: Form16AExtractedData; ocrProvider?: string };
  const payload = raw?.data ?? raw;
  const extracted = payload?.extractedData;
  const ocrProvider = payload?.ocrProvider;
  if (!extracted) {
    throw new Error((result as { message?: string }).message || 'No extracted data returned');
  }
  return { extractedData: extracted, ocrProvider };
}

export interface CreateForm16SubmissionPayload {
  financialYear: string;
  quarter: string;
  form16aNumber: string;
  tdsAmount: number;
  totalAmount: number;
  tanNumber: string;
  deductorName: string;
  version?: number;
  file: File;
  /** Optional: raw OCR extracted data for audit (stored in form16a_submissions.ocr_extracted_data). */
  extractedData?: Form16AExtractedData | null;
}

export interface CreateForm16SubmissionResponse {
  requestId: string;
  requestNumber: string;
  submissionId: number;
  /** Set when 26AS matching runs: 'success' | 'failed' | 'resubmission_needed' */
  validationStatus?: string;
  /** Reason/details returned by backend (e.g. no 26AS, amount mismatch) */
  validationNotes?: string;
  /** Credit note number when validationStatus === 'success' */
  creditNoteNumber?: string | null;
}

/**
 * Create Form 16 submission (workflow request + form16a_submissions + document upload).
 * Uses fetch + FormData so browser sets Content-Type with boundary (avoids 400).
 */
export async function createForm16Submission(payload: CreateForm16SubmissionPayload): Promise<CreateForm16SubmissionResponse> {
  const formData = new FormData();
  formData.append('document', payload.file);
  formData.append('financialYear', payload.financialYear);
  formData.append('quarter', payload.quarter);
  formData.append('form16aNumber', payload.form16aNumber);
  formData.append('tdsAmount', String(payload.tdsAmount));
  formData.append('totalAmount', String(payload.totalAmount));
  formData.append('tanNumber', payload.tanNumber);
  formData.append('deductorName', payload.deductorName);
  if (payload.version != null) formData.append('version', String(payload.version));
  if (payload.extractedData != null) {
    formData.append('ocrExtractedData', JSON.stringify(payload.extractedData));
  }

  const body = await fetchWithAuth('/form16/submissions', { method: 'POST', body: formData });
  const result = (body as { data?: CreateForm16SubmissionResponse }).data ?? body;
  const req = result as CreateForm16SubmissionResponse;
  if (!req?.requestNumber) {
    throw new Error((body as { message?: string }).message || 'Invalid response from server');
  }
  return req;
}

/** Dealer: notify RE admins when 26AS is missing/outdated for the quarter (contact admin CTA). */
export async function contactAdminForForm16Mismatch(requestId: string): Promise<void> {
  await apiClient.post(`/form16/requests/${encodeURIComponent(requestId)}/contact-admin`);
}

// ---------- RE: 26AS ----------
export interface Tds26asEntryItem {
  id: number;
  tanNumber: string;
  deductorName?: string | null;
  quarter: string;
  assessmentYear?: string | null;
  financialYear: string;
  sectionCode?: string | null;
  amountPaid?: number | null;
  taxDeducted: number;
  totalTdsDeposited?: number | null;
  natureOfPayment?: string | null;
  transactionDate?: string | null;
  dateOfBooking?: string | null;
  statusOltas?: string | null;
  remarks?: string | null;
  createdAt?: string;
  updatedAt?: string;
}

export interface List26asParams {
  financialYear?: string;
  quarter?: string;
  tanNumber?: string;
  search?: string;
  status?: string;
  assessmentYear?: string;
  sectionCode?: string;
  limit?: number;
  offset?: number;
}

export interface List26asSummary {
  totalRecords: number;
  booked: number;
  notBooked: number;
  pending: number;
  totalTaxDeducted: number;
}

export async function list26asEntries(params?: List26asParams): Promise<{
  entries: Tds26asEntryItem[];
  total: number;
  summary: List26asSummary;
}> {
  const searchParams = new URLSearchParams();
  if (params?.financialYear) searchParams.set('financialYear', params.financialYear);
  if (params?.quarter) searchParams.set('quarter', params.quarter);
  if (params?.tanNumber) searchParams.set('tanNumber', params.tanNumber);
  if (params?.search) searchParams.set('search', params.search);
  if (params?.status) searchParams.set('status', params.status);
  if (params?.assessmentYear) searchParams.set('assessmentYear', params.assessmentYear);
  if (params?.sectionCode) searchParams.set('sectionCode', params.sectionCode);
  if (params?.limit != null) searchParams.set('limit', String(params.limit));
  if (params?.offset != null) searchParams.set('offset', String(params.offset));
  const query = searchParams.toString();
  const url = query ? `/form16/26as?${query}` : '/form16/26as';
  const { data } = await apiClient.get<{
    data?: { entries?: Tds26asEntryItem[]; total?: number; summary?: List26asSummary };
    entries?: Tds26asEntryItem[];
    total?: number;
    summary?: List26asSummary;
  }>(url);
  const payload = data?.data ?? data;
  return {
    entries: payload?.entries ?? [],
    total: payload?.total ?? 0,
    summary: payload?.summary ?? {
      totalRecords: 0,
      booked: 0,
      notBooked: 0,
      pending: 0,
      totalTaxDeducted: 0,
    },
  };
}

export async function create26asEntry(body: Partial<Tds26asEntryItem>): Promise<{ entry: Tds26asEntryItem }> {
  const { data } = await apiClient.post<{ data?: { entry?: Tds26asEntryItem }; entry?: Tds26asEntryItem }>('/form16/26as', body);
  const payload = data?.data ?? data;
  const entry = (payload?.entry ?? payload) as Tds26asEntryItem | undefined;
  if (!entry || typeof entry !== 'object') throw new Error('No entry returned');
  return { entry };
}

export async function update26asEntry(id: number, body: Partial<Tds26asEntryItem>): Promise<{ entry: Tds26asEntryItem }> {
  const { data } = await apiClient.put<{ data?: { entry?: Tds26asEntryItem }; entry?: Tds26asEntryItem }>(`/form16/26as/${id}`, body);
  const payload = data?.data ?? data;
  const entry = (payload?.entry ?? payload) as Tds26asEntryItem | undefined;
  if (!entry || typeof entry !== 'object') throw new Error('No entry returned');
  return { entry };
}

export async function delete26asEntry(id: number): Promise<void> {
  await apiClient.delete(`/form16/26as/${id}`);
}

/** 26AS upload audit log entry (who uploaded, when, records imported). */
export interface Form1626asUploadHistoryItem {
  id: number;
  uploadedAt: string;
  uploadedBy: string;
  uploadedByEmail?: string | null;
  uploadedByDisplayName?: string | null;
  fileName?: string | null;
  recordsImported: number;
  errorsCount: number;
}

export async function get26asUploadHistory(limit?: number): Promise<Form1626asUploadHistoryItem[]> {
  const params = new URLSearchParams();
  if (limit != null) params.set('limit', String(limit));
  const query = params.toString();
  const url = query ? `/form16/26as/upload-history?${query}` : '/form16/26as/upload-history';
  const { data } = await apiClient.get<{ data?: { history?: Form1626asUploadHistoryItem[] }; history?: Form1626asUploadHistoryItem[] }>(url);
  const payload = data?.data ?? data;
  return payload?.history ?? [];
}

/** Timeout for 26AS upload (large files can take 1–2 min). */
const UPLOAD_26AS_TIMEOUT_MS = 5 * 60 * 1000;

export interface Upload26asResult {
  imported: number;
  errors: string[];
}

/**
 * Upload 26AS TXT file with optional progress callback (0–100%).
 * Uses XHR so we can report upload progress; after 100% the server may still be processing.
 */
export function upload26asFile(
  file: File,
  onProgress?: (percent: number) => void
): Promise<Upload26asResult> {
  return new Promise((resolve, reject) => {
    const formData = new FormData();
    formData.append('file', file);
    const xhr = new XMLHttpRequest();
    const url = `${API_BASE_URL}/form16/26as/upload`;
    const token = TokenManager.getAccessToken();

    const timeoutId = setTimeout(() => {
      xhr.abort();
      reject(new Error('Upload timed out. Try a smaller file or try again.'));
    }, UPLOAD_26AS_TIMEOUT_MS);

    xhr.upload.addEventListener('progress', (e) => {
      if (e.lengthComputable && e.total > 0) {
        const percent = Math.min(100, Math.round((e.loaded / e.total) * 100));
        onProgress?.(percent);
      } else {
        onProgress?.(0);
      }
    });

    xhr.addEventListener('load', () => {
      clearTimeout(timeoutId);
      onProgress?.(100);
      const contentType = xhr.getResponseHeader('content-type');
      const isJson = contentType?.includes('application/json');
      const raw = xhr.responseText;
      let data: { data?: { imported?: number; errors?: string[] }; message?: string };
      try {
        data = isJson ? JSON.parse(raw) : { message: raw || 'Request failed' };
      } catch {
        data = { message: raw || 'Invalid response' };
      }
      if (xhr.status >= 200 && xhr.status < 300) {
        const payload = (data.data ?? data) as { imported?: number; errors?: string[] } | undefined;
        resolve({
          imported: payload?.imported ?? 0,
          errors: Array.isArray(payload?.errors) ? payload.errors : [],
        });
      } else {
        reject(new Error((data as { message?: string }).message || `Request failed ${xhr.status}`));
      }
    });

    xhr.addEventListener('error', () => {
      clearTimeout(timeoutId);
      reject(new Error('Network error during upload'));
    });

    xhr.addEventListener('abort', () => {
      clearTimeout(timeoutId);
      reject(new Error('Upload was cancelled or timed out'));
    });

    xhr.open('POST', url);
    if (token) xhr.setRequestHeader('Authorization', `Bearer ${token}`);
    xhr.withCredentials = true;
    xhr.send(formData);
  });
}

// ---------- RE: Non-submitted dealers ----------
export interface NotificationHistoryItem {
  date: string;
  notifiedBy: string;
  method: string;
}

export interface NonSubmittedDealerItem {
  id: string;
  dealerName: string;
  dealerCode: string;
  email: string;
  phone: string;
  location: string;
  missingQuarters: string[];
  lastSubmissionDate: string | null;
  daysSinceLastSubmission: number | null;
  lastNotifiedDate: string | null;
  lastNotifiedBy: string | null;
  notificationCount: number;
  notificationHistory: NotificationHistoryItem[];
}

export interface NonSubmittedDealersSummary {
  totalDealers: number;
  nonSubmittedCount: number;
  neverSubmittedCount: number;
  overdue90Count: number;
}

export interface ListNonSubmittedDealersResponse {
  summary: NonSubmittedDealersSummary;
  dealers: NonSubmittedDealerItem[];
}

export async function listNonSubmittedDealers(financialYear?: string): Promise<ListNonSubmittedDealersResponse> {
  const params = new URLSearchParams();
  if (financialYear) params.set('financialYear', financialYear);
  const query = params.toString();
  const url = query ? `/form16/non-submitted-dealers?${query}` : '/form16/non-submitted-dealers';
  const { data } = await apiClient.get<{ data?: ListNonSubmittedDealersResponse }>(url);
  const payload = (data?.data ?? data) as ListNonSubmittedDealersResponse | undefined;
  const s = payload?.summary;
  return {
    summary: s ?? {
      totalDealers: 0,
      nonSubmittedCount: 0,
      neverSubmittedCount: 0,
      overdue90Count: 0,
    },
    dealers: payload?.dealers ?? [],
  };
}

/** Send "submit Form 16" notification to one non-submitted dealer. Returns updated dealer (with lastNotifiedDate set). */
export async function notifyNonSubmittedDealer(
  params: { dealerCode?: string | null; dealerId?: string | null; email?: string | null; financialYear?: string }
): Promise<NonSubmittedDealerItem> {
  const dealerCode = String(params.dealerCode ?? '').trim();
  const dealerId = String(params.dealerId ?? '').trim();
  const email = String(params.email ?? '').trim();
  if (!dealerCode && !dealerId && !email) {
    throw new Error('Dealer identifier missing');
  }
  const { data } = await apiClient.post<{ data?: { dealer: NonSubmittedDealerItem } }>('/form16/non-submitted-dealers/notify', {
    dealerCode: dealerCode || undefined,
    dealerId: dealerId || undefined,
    email: email || undefined,
    financialYear: params.financialYear || undefined,
  });
  const dealer = data?.data?.dealer;
  if (!dealer) throw new Error('No dealer returned');
  return dealer;
}

// ---------- Dealer: Pending Submissions page ----------
export interface DealerPendingSubmissionItem {
  id: number;
  requestId: string;
  form16a_number: string;
  financial_year: string;
  quarter: string;
  version: number;
  version_number?: number;
  status: string;
  /** Display label: Completed | Resubmission needed | Duplicate submission | Failed | Under review (never Pending) */
  display_status?: string;
  validation_status: string | null;
  submitted_date: string | null;
  total_amount?: number | null;
  credit_note_number?: string | null;
  document_url?: string | null;
}

export interface DealerPendingQuarterItem {
  financial_year: string;
  quarter: string;
  dealer_name?: string | null;
  has_submission: boolean;
  latest_submission_status: string | null;
  latest_submission_id: number | null;
  audit_start_date: string | null;
  twenty_six_as_start_date?: string | null;
  days_remaining: number | null;
  days_overdue: number | null;
  days_since_26as_uploaded?: number | null;
}

/** List dealer's Form 16 submissions (pending/failed). Dealer only. */
export async function listDealerSubmissions(params?: {
  status?: string;
  financialYear?: string;
  quarter?: string;
}): Promise<DealerPendingSubmissionItem[]> {
  const searchParams = new URLSearchParams();
  if (params?.status) searchParams.set('status', params.status);
  if (params?.financialYear) searchParams.set('financialYear', params.financialYear);
  if (params?.quarter) searchParams.set('quarter', params.quarter);
  const query = searchParams.toString();
  const url = query ? `/form16/dealer/submissions?${query}` : '/form16/dealer/submissions';
  const { data } = await apiClient.get<{ data?: DealerPendingSubmissionItem[] }>(url);
  const payload = data?.data ?? data;
  return Array.isArray(payload) ? payload : [];
}

/** List dealer's pending quarters (no completed Form 16A). Dealer only. */
export async function listDealerPendingQuarters(): Promise<DealerPendingQuarterItem[]> {
  const { data } = await apiClient.get<{ data?: DealerPendingQuarterItem[] }>('/form16/dealer/pending-quarters');
  const payload = data?.data ?? data;
  return Array.isArray(payload) ? payload : [];
}
