import { expect, test } from '@playwright/test';

/**
 * Recette R3 (plan de releases) : pièce sous le seuil → BC prérempli →
 * réception (le stock remonte, l'alerte s'éteint) ; coûts réels sur OT
 * (prix figé + taux figé) ; document rattaché téléversé puis téléchargé ;
 * statistiques lisibles par la Vue seule.
 * Chaque test crée SES données (marquées E2E, purgées au global-setup).
 */

const suffix = Date.now().toString(36);

/** PNG 1×1 valide — assez pour tester upload/download réels via MinIO. */
const PNG_1PX = Buffer.from(
  'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
  'base64',
);

async function connexionDemo(page: import('@playwright/test').Page, nom: RegExp) {
  await page.goto('/connexion');
  await page.getByRole('button', { name: nom }).click();
  await expect(page.locator('.topbar')).toBeVisible();
}

async function changerDeCompte(page: import('@playwright/test').Page, nom: RegExp) {
  await page.locator('.compte').click();
  await page.getByRole('menuitem', { name: nom }).click();
}

test('recette R3 : tiers → pièce sous seuil → BC prérempli → réception → alerte éteinte', async ({
  page,
}) => {
  const fournisseur = `E2E Fournisseur ${suffix}`;
  const piece = `E2E Pièce ${suffix}`;

  // 1 · Nadia (gestionnaire) crée le fournisseur
  await connexionDemo(page, /Nadia Berrada/);
  await page.getByRole('link', { name: 'Tiers' }).click();
  await page.getByRole('button', { name: '+ Nouveau tiers' }).click();
  await page.getByLabel('Nom *').fill(fournisseur);
  await page.getByLabel('Type *').selectOption('SUPPLIER');
  await page.getByRole('button', { name: 'Créer', exact: true }).click();
  await expect(page.getByRole('cell', { name: fournisseur })).toBeVisible();

  // 2 · Nouvelle pièce (seuil 5, prix initial 100) → fiche
  await page.getByRole('link', { name: 'Stock & achats' }).click();
  await page.getByRole('button', { name: '+ Nouvelle pièce' }).click();
  await page.getByLabel('Désignation *').fill(piece);
  await page.getByLabel("Seuil d'alerte").fill('5');
  await page.getByLabel('Prix initial (MAD)').fill('100');
  await page.getByLabel('Fournisseur', { exact: true }).selectOption({ label: fournisseur });
  await page.getByRole('button', { name: 'Créer la pièce' }).click();
  await expect(page.getByRole('heading', { name: piece })).toBeVisible();

  // 3 · Entrée de 2 → stock 2 < seuil 5 : alerte
  await page.getByRole('button', { name: 'Entrée de stock' }).click();
  await page.getByLabel(/Quantité/).fill('2');
  await page.getByRole('button', { name: 'Tracer le mouvement' }).click();
  await expect(page.locator('.entete-page .stock-bas')).toHaveText('Sous le seuil');
  await expect(page.locator('dd', { hasText: 'seuil : 5' })).toContainText('2');

  // 4 · « Préparer le BC » → formulaire prérempli (fournisseur, qté 8, PU 100)
  await page.getByRole('button', { name: 'Préparer le BC' }).click();
  await expect(page.getByRole('heading', { name: 'Nouveau bon de commande' })).toBeVisible();
  await expect(page.getByLabel('Fournisseur *')).toHaveValue(/.+/);
  await expect(page.getByLabel('Quantité de la ligne 1')).toHaveValue('8'); // seuil − stock + 5
  await expect(page.getByLabel('Prix unitaire de la ligne 1')).toHaveValue('100');
  await page.getByRole('button', { name: 'Créer le BC (brouillon)' }).click();

  // 5 · Envoyer puis réceptionner — le panneau suit le BC
  const ligneBC = page.locator('tr', { hasText: fournisseur }).first();
  await ligneBC.click();
  await expect(page.locator('.panneau .st')).toHaveText('Brouillon');
  await page.getByRole('button', { name: 'Envoyer au fournisseur' }).click();
  await expect(page.locator('.panneau .st')).toHaveText('Envoyé');
  await page.getByRole('button', { name: /Réceptionner/ }).click();
  await expect(page.locator('.panneau .st')).toHaveText('Reçu');

  // 6 · Le stock est remonté (2 + 8 = 10), l'alerte est éteinte
  await page.getByRole('link', { name: 'Stock & achats' }).click();
  const lignePiece = page.locator('tr', { hasText: piece });
  await expect(lignePiece.locator('td').nth(2)).toHaveText('10');
  await expect(lignePiece.locator('.stock-bas')).toHaveCount(0);

  // 7 · La fiche pièce raconte tout : entrée manuelle + réception à PU figé
  await lignePiece.click();
  await expect(page.locator('.mvt.entree')).toHaveCount(2);
  await expect(page.getByText('100 MAD/u')).toBeVisible();
});

test('recette R3 : coûts réels sur OT (prix + taux figés) + document + statistiques', async ({
  page,
}) => {
  const piece = `E2E PièceOT ${suffix}`;
  const titreOT = `E2E ${suffix} — coûts`;

  // 1 · Nadia crée une pièce avec du stock (10 à 100 MAD)
  await connexionDemo(page, /Nadia Berrada/);
  await page.getByRole('link', { name: 'Stock & achats' }).click();
  await page.getByRole('button', { name: '+ Nouvelle pièce' }).click();
  await page.getByLabel('Désignation *').fill(piece);
  await page.getByLabel('Prix initial (MAD)').fill('100');
  await page.getByRole('button', { name: 'Créer la pièce' }).click();
  await expect(page.getByRole('heading', { name: piece })).toBeVisible();
  await page.getByRole('button', { name: 'Entrée de stock' }).click();
  await page.getByLabel(/Quantité/).fill('10');
  await page.getByRole('button', { name: 'Tracer le mouvement' }).click();
  await expect(page.locator('dd', { hasText: 'seuil : 0' })).toContainText('10');

  // 2 · Salma (dispatcher) crée l'OT et l'assigne à Ahmed
  await changerDeCompte(page, /Salma Idrissi/);
  await page.getByRole('link', { name: /Ordres de travail/ }).click();
  await page.getByRole('button', { name: '+ Nouvel OT' }).click();
  await page.getByLabel('Objet *').fill(titreOT);
  await page.getByLabel('Équipement *').selectOption({ index: 1 });
  await page.getByLabel('Assigner à').selectOption({ label: 'Ahmed Benali' });
  await page.getByRole('button', { name: "Créer l'OT (statut Ouvert)" }).click();
  await expect(page.getByRole('heading', { name: titreOT })).toBeVisible();

  // 3 · Ahmed (technicien) démarre, consomme 2 pièces, saisit 1 h 30
  await changerDeCompte(page, /Ahmed Benali/);
  await page.getByRole('link', { name: /Ordres de travail/ }).click();
  await page.getByRole('cell', { name: titreOT }).click();
  await page.getByRole('button', { name: 'Démarrer' }).click();
  await expect(page.locator('.entete-page .st')).toHaveText('En cours');

  await page.getByRole('button', { name: '+ Consommer une pièce' }).click();
  await page.getByLabel('Pièce *').selectOption({ label: `${piece} — stock : 10` });
  await expect(page.getByText('Prix figé à la consommation')).toBeVisible();
  await page.getByLabel('Quantité *').fill('2');
  await page.getByRole('button', { name: /^Consommer/ }).click();
  await expect(page.locator('.item-liste', { hasText: `${piece} × 2` })).toBeVisible();

  await page.getByRole('button', { name: '+ Saisir du temps' }).click();
  await page.getByLabel('Heures').fill('1');
  await page.getByLabel('Minutes').fill('30');
  await page.getByRole('button', { name: 'Enregistrer' }).click();
  // 2 × 100 + 1,5 h × 120 MAD/h (taux seedé d'Ahmed) = 380 MAD
  await expect(page.getByText('1 h 30 × 120 MAD/h')).toBeVisible();
  await expect(page.locator('.total .num')).toHaveText('380 MAD');

  // 4 · Ahmed joint une photo — puis la retélécharge (aller-retour MinIO réel)
  await page.getByLabel('Choisir un fichier').setInputFiles({
    name: `photo-e2e-${suffix}.png`,
    mimeType: 'image/png',
    buffer: PNG_1PX,
  });
  await expect(page.getByText(`photo-e2e-${suffix}.png`)).toBeVisible();
  const attenteTelechargement = page.waitForEvent('download');
  await page.getByRole('button', { name: 'Télécharger' }).click();
  expect((await attenteTelechargement).suggestedFilename()).toBe(`photo-e2e-${suffix}.png`);

  // 5 · Rachid (vue seule) lit les statistiques
  await changerDeCompte(page, /Rachid Bennis/);
  await page.getByRole('link', { name: 'Statistiques', exact: true }).click();
  await expect(page.getByText('OT clôturés · 12 mois')).toBeVisible();
  await expect(page.getByText('Pannes par organe · 12 mois')).toBeVisible();
  await expect(page.getByText('Top équipements en coût · 12 mois')).toBeVisible();
});

test('recette R3 corrigée : recherche ⌘K, tri/filtre stock, période stats, rattachements, dépôt', async ({
  page,
}) => {
  await connexionDemo(page, /Yasmine Alaoui/);

  // Recherche globale : ⌘K → site (insensible à la casse), clic → fiche site
  await page.keyboard.press('ControlOrMeta+k');
  await page.keyboard.type('atlas');
  await page.locator('.resultat', { hasText: 'Tour Atlas' }).first().click();
  await expect(page).toHaveURL(/\/sites\//);
  // le site porte son syndic (rattachement seedé, éditable par l'admin)
  await expect(page.getByLabel('Client / syndic du site')).toHaveValue(/.+/);

  // Recherche OT au clavier seul (Entrée sur le premier résultat)
  await page.keyboard.press('ControlOrMeta+k');
  await page.keyboard.type('bruit');
  await page.locator('.resultat', { hasText: 'Bruit anormal' }).first().waitFor();
  await page.keyboard.press('Enter');
  await expect(page).toHaveURL(/\/ot\//);

  // Stock : les pièces sous le seuil remontent en tête, filtre fournisseur,
  // « Entrée de stock » accessible depuis la liste (choix de la pièce)
  await page.getByRole('link', { name: 'Stock & achats' }).click();
  await expect(page.locator('tbody tr').first().locator('.stock-bas')).toHaveText(/Sous le seuil/);
  await page.getByLabel('Filtrer par fournisseur').selectOption({ label: 'Lubmaroc' });
  await expect(page.locator('tbody tr', { hasText: 'P-0042' })).toHaveCount(1);
  await page.getByLabel('Filtrer par fournisseur').selectOption({ index: 0 });
  await page.getByRole('button', { name: 'Entrée de stock' }).click();
  await expect(page.getByLabel('Pièce *')).toBeVisible();
  await page.getByRole('button', { name: 'Annuler' }).click();

  // Fiche pièce : le fournisseur est un lien vers les tiers
  await page.getByRole('cell', { name: 'P-0113' }).click();
  await page.getByRole('link', { name: 'Ascentech Maroc' }).click();
  await expect(page).toHaveURL(/\/tiers/);
  // Tiers : les syndics affichent leurs sites
  await expect(page.getByRole('cell', { name: 'Tour Atlas' })).toBeVisible();
  await expect(page.getByRole('cell', { name: 'Résidence Al Manar' })).toBeVisible();

  // Statistiques : la période est un vrai sélecteur
  await page.getByRole('link', { name: 'Statistiques', exact: true }).click();
  await page.getByLabel('Période').selectOption('3');
  await expect(page.getByText('OT clôturés · 3 mois')).toBeVisible();

  // Bibliothèque : filtre « Rattaché à » + zone de glisser-déposer
  await page.getByRole('link', { name: 'Fichiers' }).click();
  await expect(page.getByLabel('Filtrer par appareil')).toBeVisible();
  await expect(page.locator('.zone-depot')).toBeVisible();
});
