// Behavioral test of the absolute-snapshot pinch fix (6829076) — device-
// independent (no pdfrx). Simulates a two-finger pinch over PenCanvas and
// samples the shared transform's scale each frame: a steady spread must grow
// the scale MONOTONICALLY, never spiking above the final value and snapping
// back (the reported flicker the fix removes).

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:badnote/editor/canvas/pen_canvas.dart';
import 'package:badnote/editor/canvas/pen_stroke.dart';

void main() {
  const pageSize = Size(400, 600);

  Widget host(TransformationController controller) => MaterialApp(
        home: Scaffold(
          body: Center(
            child: SizedBox(
              width: pageSize.width,
              height: pageSize.height,
              child: PenCanvas(
                pageWidget: Container(color: const Color(0xFFEEEEEE)),
                pageSize: pageSize,
                strokes: const <PenStroke>[],
                transformationController: controller,
                tool: CanvasTool.pen,
                color: const Color(0xFF000000),
                strokeWidth: 0.004,
                onStrokeComplete: (_) {},
                onEraseStroke: (_, __) {},
              ),
            ),
          ),
        ),
      );

  testWidgets('a steady two-finger spread grows scale monotonically (no spike)',
      (tester) async {
    final controller = TransformationController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(host(controller));

    final center = tester.getCenter(find.byType(PenCanvas));
    final f1 = await tester.startGesture(
        center + const Offset(-20, 0), kind: PointerDeviceKind.touch);
    final f2 = await tester.startGesture(
        center + const Offset(20, 0), kind: PointerDeviceKind.touch);

    final scales = <double>[];
    for (var i = 0; i < 8; i++) {
      // Spread the fingers apart symmetrically (pure zoom-in, focal steady).
      await f1.moveBy(const Offset(-8, 0));
      await f2.moveBy(const Offset(8, 0));
      await tester.pump();
      scales.add(controller.value.getMaxScaleOnAxis());
    }
    await f1.up();
    await f2.up();
    await tester.pump();

    final maxScale = scales.reduce((a, b) => a > b ? a : b);
    final finalScale = scales.last;

    // Zoom actually happened.
    expect(finalScale, greaterThan(1.0));
    // No frame spiked ABOVE the final scale and snapped back — the fix's
    // invariant. (Allow a tiny epsilon for fp.)
    expect(maxScale, lessThanOrEqualTo(finalScale + 1e-6),
        reason: 'a frame popped bigger than the final scale — flicker');
    // Monotonic non-decreasing across the steady spread.
    for (var i = 1; i < scales.length; i++) {
      expect(scales[i], greaterThanOrEqualTo(scales[i - 1] - 1e-6),
          reason: 'scale went backwards at frame $i: $scales');
    }
  });

  testWidgets('the stylus never pans/zooms (excluded from the recognizer)',
      (tester) async {
    final controller = TransformationController();
    addTearDown(controller.dispose);
    await tester.pumpWidget(host(controller));

    final center = tester.getCenter(find.byType(PenCanvas));
    // A single stylus drag must DRAW, not pan — the transform stays identity.
    final g = await tester.startGesture(center, kind: PointerDeviceKind.stylus);
    await g.moveBy(const Offset(40, 40));
    await g.up();
    await tester.pump();

    expect(controller.value.getMaxScaleOnAxis(), closeTo(1.0, 1e-9));
    expect(controller.value.getTranslation().x, closeTo(0, 1e-6));
    expect(controller.value.getTranslation().y, closeTo(0, 1e-6));
  });
}
