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

/**
 * T-E2E-003 — the month-end billing arc (invoices.md M6): create an invoice
 * inline while applying eligible entries to it, confirm the lock + totals,
 * copy the PlusROI paste block (verified), then detach and confirm the
 * partition is restored (entries back to unlocked / Pending, invoice empty).
 *
 * All state assertions (toasts, stat totals, empty-state copy) — no pixels.
 * rian (AUTH_DEV_USER) is the owner, so the owner-only Apply/Detach controls
 * are present. Seed expectation: at least one PENDING entry exists to apply.
 */

test.describe('T-E2E-003 invoice apply / paste / detach', () => {
  test('apply locks entries, paste copies verified, detach restores the partition', async ({
    page,
  }) => {
    const invoiceName = `E2E ${Date.now()}`; // unique per run — runs are additive

    // --- apply ONE pending entry into a brand-new invoice ----------------
    await page.goto('/entries?status=pending&date=all&sort=date&dir=desc');
    await expect(page.getByRole('heading', { level: 1, name: 'Entries' })).toBeVisible();

    const rowCheckbox = page.getByRole('checkbox', { name: 'Select row' }).first();
    await expect(rowCheckbox).toBeVisible();
    await rowCheckbox.check();

    const bulkBar = page.getByRole('region', { name: 'Bulk actions' });
    // SELECTOR-REVIEW: the toggle button ("Apply to invoice ▾") lives in
    // `.bulk-bar-row`; the panel's inner "Apply to invoice" button lives in
    // `.bulk-panel`. Scope to the row to hit the toggle unambiguously.
    await bulkBar
      .locator('.bulk-bar-row')
      .getByRole('button', { name: /Apply to invoice/ })
      .click();

    // create-and-apply inline (ApplyInvoicePanel quick-create)
    await page.getByPlaceholder('e.g. 2026-04 PlusROI').fill(invoiceName);
    await page.getByRole('button', { name: 'Create + apply' }).click();

    const applyConfirm = page.getByRole('alertdialog', { name: 'Confirm bulk action' });
    await expect(applyConfirm).toContainText(invoiceName);
    await applyConfirm.getByRole('button', { name: /^Confirm/ }).click();

    const appliedToast = page.locator('.toast-success', { hasText: 'Applied' });
    await expect(appliedToast).toContainText(invoiceName);
    await expect(appliedToast).toContainText('verified');

    // --- open the invoice: locked totals ---------------------------------
    await page.goto('/invoices');
    await page.getByRole('link', { name: invoiceName }).click();
    await page.waitForURL(/\/invoices\/[^/]+$/);
    await expect(page.getByRole('heading', { level: 1 })).toContainText(invoiceName);

    // 1 entry attached — the lock made it a first-class invoice line.
    const entriesStat = page.locator('.entries-summary-stat').filter({ hasText: 'Entries' });
    await expect(entriesStat).toContainText('1');

    // --- copy the paste block (pessimistic, verified) --------------------
    const paste = page.locator('.invoice-paste');
    await expect(paste.getByRole('heading', { name: /Paste block/ })).toBeVisible();
    await paste.getByRole('button', { name: 'Copy to clipboard' }).click();
    // The copy button re-fetches the block, copies THAT, and reports the
    // verified line count. Clipboard perms are granted in playwright.config.
    // SELECTOR-REVIEW: if clipboard is unavailable this toast is an error
    // ("Copy failed…"); the config grants clipboard-read/write to avoid it.
    await expect(page.locator('.toast-success', { hasText: /Copied \d+ line/ })).toBeVisible();

    // --- detach: partition restored --------------------------------------
    // The detail footer links to this invoice's attached entries on /entries.
    await page.getByRole('link', { name: /View the .* attached entries/ }).click();
    await page.waitForURL(/\/entries\?/);
    await expect(page.getByRole('heading', { level: 1, name: 'Entries' })).toBeVisible();

    const appliedCheckbox = page.getByRole('checkbox', { name: 'Select row' }).first();
    await expect(appliedCheckbox).toBeVisible();
    await appliedCheckbox.check();

    const bulkBar2 = page.getByRole('region', { name: 'Bulk actions' });
    await bulkBar2.getByRole('button', { name: 'Detach' }).click();
    const detachConfirm = page.getByRole('alertdialog', { name: 'Confirm bulk action' });
    await detachConfirm.getByRole('button', { name: /^Confirm/ }).click();

    // verified detach toast: back to unlocked / Pending
    await expect(page.locator('.toast-success', { hasText: /Detached \d+/ })).toContainText(
      'Pending',
    );

    // invoice is now empty — the lock partition is restored
    await page.goto('/invoices');
    await page.getByRole('link', { name: invoiceName }).click();
    await page.waitForURL(/\/invoices\/[^/]+$/);
    const entriesStatAfter = page.locator('.entries-summary-stat').filter({ hasText: 'Entries' });
    await expect(entriesStatAfter).toContainText('0');
    await expect(page.getByText('No entries attached yet.')).toBeVisible();
  });
});
