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

import 'package:feature_orders/feature_orders.dart';
import 'package:feature_orders/src/presentation/widgets/add_note_dialog.dart';
import 'package:feature_orders/src/presentation/widgets/order_detail_panel.dart';

// ── Helpers ────────────────────────────────────────────────────────────────────

final _sampleOrder = Order(
  id: 'KC-9999',
  customerName: 'Test Customer',
  customerEmail: 'test@example.com',
  customerPhone: '555-0100',
  orderDate: DateTime(2026, 4, 1),
  status: OrderStatus.pending,
  shippingAddress: '123 Test St, Test City, TS 00000',
  items: const [
    OrderItem(productName: 'Test Product', sku: 'TP-001', quantity: 2, unitPrice: 10.00),
  ],
);

final _orderWithNotes = Order(
  id: 'KC-8888',
  customerName: 'Noted Customer',
  customerEmail: 'noted@example.com',
  orderDate: DateTime(2026, 4, 2),
  status: OrderStatus.processing,
  shippingAddress: '456 Note Ave, Test City, TS 00001',
  items: const [OrderItem(productName: 'Widget', sku: 'WG-001', quantity: 1, unitPrice: 5.00)],
  orderNotes: ['Please gift wrap.', 'Fragile item.'],
);

Widget _buildPanel(
  Order order, {
  bool isUpdating = false,
  void Function(OrderStatus)? onUpdateStatus,
  VoidCallback? onAddNote,
}) {
  return MaterialApp(
    theme: buildKcTheme(),
    home: Scaffold(
      body: SingleChildScrollView(
        child: OrderDetailPanel(
          order: order,
          isUpdating: isUpdating,
          onUpdateStatus: onUpdateStatus,
          onAddNote: onAddNote,
        ),
      ),
    ),
  );
}

Widget _buildPage(OrdersRepository repository) {
  return MaterialApp(
    theme: buildKcTheme(),
    home: Scaffold(body: OrdersPage(repository: repository)),
  );
}

// ── Test doubles ───────────────────────────────────────────────────────────────

class _EmptyOrdersRepository implements OrdersRepository {
  @override
  Future<List<Order>> getOrders() async => [];

  @override
  Future<OrderActionResult> updateOrderStatus(String id, OrderStatus newStatus) async =>
      const OrderActionResult.failure('Not implemented.');

  @override
  Future<OrderActionResult> addOrderNote(String id, String note) async =>
      const OrderActionResult.failure('Not implemented.');

  @override
  Future<OrderActionResult> createOrder(Order order) async =>
      const OrderActionResult.failure('Not implemented.');
}

// ── Tests ──────────────────────────────────────────────────────────────────────

void main() {
  // ── OrderDetailPanel ───────────────────────────────────────────────────────

  group('OrderDetailPanel', () {
    testWidgets('displays order ID in header', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('Order KC-9999'), findsOneWidget);
    });

    testWidgets('displays status chip', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('Pending'), findsOneWidget);
    });

    testWidgets('displays customer name', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('Test Customer'), findsOneWidget);
    });

    testWidgets('displays customer email', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('test@example.com'), findsOneWidget);
    });

    testWidgets('displays customer phone when present', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('555-0100'), findsOneWidget);
    });

    testWidgets('displays shipping address', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('123 Test St, Test City, TS 00000'), findsOneWidget);
    });

    testWidgets('displays line item product name', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('Test Product'), findsOneWidget);
    });

    testWidgets('displays order total', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      // 2 * 10.00 = 20.00 — appears in line item and in total row
      expect(find.text('\$20.00'), findsWidgets);
    });

    testWidgets('shows status dropdown when onUpdateStatus is provided', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder, onUpdateStatus: (_) {}));
      expect(find.text('Update Status'), findsOneWidget);
      expect(find.byType(DropdownButtonFormField<OrderStatus>), findsOneWidget);
    });

    testWidgets('hides status dropdown when onUpdateStatus is null', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('Update Status'), findsNothing);
      expect(find.byType(DropdownButtonFormField<OrderStatus>), findsNothing);
    });

    testWidgets('shows Add Note button when onAddNote is provided', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder, onAddNote: () {}));
      expect(find.text('Add Note'), findsOneWidget);
    });

    testWidgets('hides Add Note button when onAddNote is null', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('Add Note'), findsNothing);
    });

    testWidgets('shows loading indicator when isUpdating is true', (tester) async {
      await tester.pumpWidget(
        _buildPanel(_sampleOrder, isUpdating: true, onUpdateStatus: (_) {}, onAddNote: () {}),
      );
      expect(find.byType(CircularProgressIndicator), findsOneWidget);
      // Actions hidden during update
      expect(find.text('Update Status'), findsNothing);
      expect(find.text('Add Note'), findsNothing);
    });

    testWidgets('displays order notes when present', (tester) async {
      await tester.pumpWidget(_buildPanel(_orderWithNotes));
      expect(find.text('Please gift wrap.'), findsOneWidget);
      expect(find.text('Fragile item.'), findsOneWidget);
    });

    testWidgets('hides notes section when orderNotes is empty', (tester) async {
      await tester.pumpWidget(_buildPanel(_sampleOrder));
      expect(find.text('Notes'), findsNothing);
    });

    testWidgets('calls onAddNote when Add Note button is tapped', (tester) async {
      var called = false;
      await tester.pumpWidget(_buildPanel(_sampleOrder, onAddNote: () => called = true));
      await tester.tap(find.text('Add Note'));
      await tester.pump();
      expect(called, true);
    });
  });

  // ── AddNoteDialog ──────────────────────────────────────────────────────────

  group('AddNoteDialog', () {
    testWidgets('shows dialog title and text field', (tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: buildKcTheme(),
          home: Builder(
            builder: (context) => Scaffold(
              body: ElevatedButton(
                onPressed: () => showAddNoteDialog(context),
                child: const Text('Open'),
              ),
            ),
          ),
        ),
      );
      await tester.tap(find.text('Open'));
      await tester.pumpAndSettle();

      // Dialog title "Add Note" and button "Add Note" both appear — use findsWidgets
      expect(find.text('Add Note'), findsWidgets);
      expect(find.byType(TextField), findsOneWidget);
    });

    testWidgets('shows validation error when submitting empty note', (tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: buildKcTheme(),
          home: Builder(
            builder: (context) => Scaffold(
              body: ElevatedButton(
                onPressed: () => showAddNoteDialog(context),
                child: const Text('Open'),
              ),
            ),
          ),
        ),
      );
      await tester.tap(find.text('Open'));
      await tester.pumpAndSettle();

      // Tap Add Note without entering text
      await tester.tap(find.widgetWithText(FilledButton, 'Add Note'));
      await tester.pump();

      expect(find.text('Note cannot be empty.'), findsOneWidget);
    });

    testWidgets('dismisses dialog on Cancel', (tester) async {
      await tester.pumpWidget(
        MaterialApp(
          theme: buildKcTheme(),
          home: Builder(
            builder: (context) => Scaffold(
              body: ElevatedButton(
                onPressed: () => showAddNoteDialog(context),
                child: const Text('Open'),
              ),
            ),
          ),
        ),
      );
      await tester.tap(find.text('Open'));
      await tester.pumpAndSettle();

      await tester.tap(find.text('Cancel'));
      await tester.pumpAndSettle();

      expect(find.text('Add Note'), findsNothing);
    });
  });

  // ── OrdersPage ─────────────────────────────────────────────────────────────

  group('OrdersPage', () {
    testWidgets('shows loading state initially', (tester) async {
      await tester.pumpWidget(_buildPage(FakeOrdersRepository()));
      expect(find.byType(CircularProgressIndicator), findsOneWidget);
      // Drain pending timers so the widget tree can be disposed cleanly.
      await tester.pumpAndSettle();
    });

    testWidgets('shows order list after load', (tester) async {
      await tester.pumpWidget(_buildPage(FakeOrdersRepository()));
      await tester.pumpAndSettle();
      // FakeOrdersRepository has 6 orders
      expect(find.byType(OrderCard), findsWidgets);
    });

    testWidgets('shows search bar', (tester) async {
      await tester.pumpWidget(_buildPage(FakeOrdersRepository()));
      await tester.pumpAndSettle();
      expect(find.byType(TextField), findsOneWidget);
    });

    testWidgets('shows filter chips for all statuses', (tester) async {
      await tester.pumpWidget(_buildPage(FakeOrdersRepository()));
      await tester.pumpAndSettle();
      expect(find.text('All'), findsOneWidget);
      // Status labels appear in both filter chips and order cards — use findsWidgets
      expect(find.text('Pending'), findsWidgets);
      expect(find.text('Processing'), findsWidgets);
      expect(find.text('Shipped'), findsWidgets);
      expect(find.text('Delivered'), findsWidgets);
      expect(find.text('Cancelled'), findsWidgets);
    });

    testWidgets('shows order count', (tester) async {
      await tester.pumpWidget(_buildPage(FakeOrdersRepository()));
      await tester.pumpAndSettle();
      expect(find.text('6 orders'), findsOneWidget);
    });

    testWidgets('shows empty state when repository returns no orders', (tester) async {
      await tester.pumpWidget(_buildPage(_EmptyOrdersRepository()));
      await tester.pumpAndSettle();
      expect(find.text('No orders found. Try adjusting your search or filter.'), findsOneWidget);
    });
  });
}
