import apiClient, { buildApiUrl, getApiAccessToken } from "./apiClient";
import { saveDevisPdfToCacheFile } from "../core/fileStorage";
import type { ApiEnvelope } from "../types/auth";

/**
 * Devis d'une machine, tel qu'expose par /api/devis.php (Bearer JWT mobile
 * accepte en priorite par AuthMiddleware::checkAuth, scoping tenant garanti
 * par MobileJwtMiddleware). On ne type que les champs consommes par le rendu
 * des etapes "LISTE DEVIS *" ; le reste du payload est ignore.
 */
export type DevisItem = {
  id: number;
  numero_devis?: string | null;
  statut?: string | null;
  montant?: number | string | null;
  date_devis?: string | null;
  [key: string]: unknown;
};

/**
 * Recupere les devis d'une machine, tries created_at DESC cote serveur
 * (data[0] = devis le plus recent). Silent-fail : la liste devis n'est pas
 * critique pour le workflow, donc toute erreur reseau/HTTP retombe sur une
 * liste vide — meme contrat que la PWA (public/js/intervention_etapes.js).
 */
export async function getDevisForMachine(machineId: number): Promise<DevisItem[]> {
  if (!machineId) {
    return [];
  }
  try {
    const response = await apiClient.get<ApiEnvelope<DevisItem[]>>("/devis.php", {
      params: { machine_id: machineId },
    });
    const data = response.data?.data;
    return Array.isArray(data) ? data : [];
  } catch {
    return [];
  }
}

// Type minimal du module natif expo-sharing (require paresseux). On ne declare
// que ce qu'on consomme : evite un import statique du module natif (absent d'un
// binaire pre-rebuild -> crash au chargement) et garde tsc decouple du package.
type SharingModule = {
  isAvailableAsync: () => Promise<boolean>;
  shareAsync: (uri: string, options?: Record<string, unknown>) => Promise<void>;
};

/**
 * Message d'erreur lisible pour le technicien selon le statut de
 * /api/devis_pdf.php. Contrairement a getDevisForMachine (silent-fail), ici
 * l'utilisateur a explicitement clique "Voir le devis" -> il faut un retour
 * clair, jamais un crash ni un echec muet.
 */
function devisPdfErrorMessage(status: number): string {
  if (status === 403) return "Ce devis n'est pas accessible (hors de votre périmètre).";
  if (status === 404) return "Devis introuvable ou fichier PDF absent.";
  if (status === 422) return "Référence de devis invalide.";
  return "Impossible de récupérer le devis. Réessayez plus tard.";
}

/**
 * Telecharge le PDF d'un devis en BINAIRE avec le Bearer mobile en HEADER (jamais
 * en query string ni en log) et le met en cache local, renvoyant son URI fichier.
 * apiClient.get() ne gere que du JSON -> on fait un fetch brut. Le routage par
 * backend (coolcare / missioflow-app) est porte par buildApiUrl, donc aucun
 * branchement conditionnel : meme path /api/devis_pdf.php sur les 2 backends.
 */
export async function downloadDevisPdf(devisId: number): Promise<string> {
  if (!Number.isFinite(devisId) || devisId <= 0) {
    throw new Error(devisPdfErrorMessage(422));
  }
  const url = await buildApiUrl(`/devis_pdf.php?id=${devisId}`);
  const token = await getApiAccessToken();
  const response = await fetch(url, {
    headers: token ? { Authorization: `Bearer ${token}` } : {},
  });
  if (!response.ok) {
    throw new Error(devisPdfErrorMessage(response.status));
  }
  const bytes = new Uint8Array(await response.arrayBuffer());
  return saveDevisPdfToCacheFile(devisId, bytes);
}

/**
 * Telecharge puis ouvre le PDF d'un devis via la feuille de partage/apercu OS
 * (expo-sharing). Le module natif est charge en require PARESSEUX : sur un
 * binaire ne l'embarquant pas encore (OTA avant rebuild), l'echec est confine a
 * ce clic (erreur attrapable) au lieu de planter le chargement de l'ecran.
 */
export async function openDevisPdf(devisId: number): Promise<void> {
  const localUri = await downloadDevisPdf(devisId);
  // eslint-disable-next-line @typescript-eslint/no-var-requires
  const Sharing = require("expo-sharing") as SharingModule;
  if (!(await Sharing.isAvailableAsync())) {
    throw new Error("Le partage de fichiers n'est pas disponible sur cet appareil.");
  }
  await Sharing.shareAsync(localUri, {
    mimeType: "application/pdf",
    UTI: "com.adobe.pdf",
    dialogTitle: "Devis",
  });
}
