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

import 'package:feature_wordpress/feature_wordpress.dart';
import 'package:feature_wordpress/src/presentation/widgets/product_preview_panel.dart';

void main() {
  final sampleDraft = ProductDraft(
    id: '1',
    name: 'Test Bowl Cozy',
    description: 'A beautifully crafted test product.',
    price: 12.99,
    sku: 'BC-TST-001',
    category: 'Bowl Cozies',
    imageUrl: '',
    status: PublishStatus.draft,
    lastModified: DateTime(2026, 4, 1),
  );

  final draftWithImageUrl = ProductDraft(
    id: '7',
    name: 'Product With Image',
    description: 'Has an image URL.',
    price: 25.00,
    sku: 'IMG-001',
    category: 'Bowl Cozies',
    imageUrl: 'https://example.com/product.jpg',
    status: PublishStatus.draft,
    lastModified: DateTime(2026, 4, 5),
  );

  final publishedDraft = ProductDraft(
    id: '2',
    name: 'Published Product',
    description: 'Already published.',
    price: 19.99,
    sku: 'PP-001',
    category: 'Coasters',
    imageUrl: '',
    status: PublishStatus.published,
    lastModified: DateTime(2026, 3, 28),
  );

  final pendingDraft = ProductDraft(
    id: '3',
    name: 'Pending Product',
    description: 'Awaiting review.',
    price: 14.99,
    sku: 'PR-001',
    category: 'Nightlights',
    imageUrl: '',
    status: PublishStatus.pendingReview,
    lastModified: DateTime(2026, 4, 1),
  );

  final unpublishedDraft = ProductDraft(
    id: '4',
    name: 'Unpublished Product',
    description: 'Previously published but taken down.',
    price: 9.99,
    sku: 'UP-001',
    category: 'Coasters',
    imageUrl: '',
    status: PublishStatus.unpublished,
    lastModified: DateTime(2026, 3, 20),
  );

  Widget buildTestWidget(
    ProductDraft draft, {
    VoidCallback? onPublish,
    VoidCallback? onMoveToDraft,
    ValueChanged<double>? onPriceChanged,
    ValueChanged<String>? onNameChanged,
    bool isUpdating = false,
  }) {
    return MaterialApp(
      theme: buildKcTheme(),
      home: Scaffold(
        body: SingleChildScrollView(
          child: ProductPreviewPanel(
            draft: draft,
            onPublish: onPublish,
            onMoveToDraft: onMoveToDraft,
            onPriceChanged: onPriceChanged,
            onNameChanged: onNameChanged,
            isUpdating: isUpdating,
          ),
        ),
      ),
    );
  }

  group('ProductPreviewPanel', () {
    testWidgets('displays product name', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('Test Bowl Cozy'), findsOneWidget);
    });

    testWidgets('displays description', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('A beautifully crafted test product.'), findsOneWidget);
    });

    testWidgets('displays SKU metadata', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('BC-TST-001'), findsOneWidget);
    });

    testWidgets('displays price metadata', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('\$12.99'), findsOneWidget);
    });

    testWidgets('displays category metadata', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('Bowl Cozies'), findsOneWidget);
    });

    testWidgets('displays last modified date', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('2026-04-01'), findsOneWidget);
    });

    testWidgets('calls onPublish when button is tapped', (tester) async {
      var published = false;
      await tester.pumpWidget(buildTestWidget(sampleDraft, onPublish: () => published = true));
      await tester.tap(find.text('Publish to Store'));
      expect(published, true);
    });
  });

  group('image display', () {
    testWidgets('shows placeholder icon when imageUrl is empty', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.byIcon(Icons.image_outlined), findsOneWidget);
    });

    testWidgets('hides Image URL metadata row when imageUrl is empty', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('Image URL'), findsNothing);
    });

    testWidgets('shows Image URL metadata row when imageUrl is present', (tester) async {
      await tester.pumpWidget(buildTestWidget(draftWithImageUrl));
      expect(find.text('Image URL'), findsOneWidget);
      expect(find.text('https://example.com/product.jpg'), findsOneWidget);
    });

    testWidgets('renders Image.network when imageUrl is present', (tester) async {
      await tester.pumpWidget(buildTestWidget(draftWithImageUrl));
      expect(find.byType(Image), findsOneWidget);
    });

    testWidgets('does not render Image.network when imageUrl is empty', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.byType(Image), findsNothing);
    });
  });

  group('status-aware action buttons', () {
    testWidgets('draft row shows Publish to Store button', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.text('Publish to Store'), findsOneWidget);
      expect(find.text('Move to Draft'), findsNothing);
    });

    testWidgets('published row shows Move to Draft button', (tester) async {
      await tester.pumpWidget(buildTestWidget(publishedDraft));
      expect(find.text('Move to Draft'), findsOneWidget);
      expect(find.text('Publish to Store'), findsNothing);
    });

    testWidgets('pending review row shows Move to Draft button', (tester) async {
      await tester.pumpWidget(buildTestWidget(pendingDraft));
      expect(find.text('Move to Draft'), findsOneWidget);
      expect(find.text('Publish to Store'), findsNothing);
    });

    testWidgets('calls onMoveToDraft when Move to Draft is tapped for pending review', (
      tester,
    ) async {
      var movedToDraft = false;
      await tester.pumpWidget(
        buildTestWidget(pendingDraft, onMoveToDraft: () => movedToDraft = true),
      );
      await tester.tap(find.text('Move to Draft'));
      expect(movedToDraft, true);
    });

    testWidgets('calls onMoveToDraft when Move to Draft is tapped', (tester) async {
      var movedToDraft = false;
      await tester.pumpWidget(
        buildTestWidget(publishedDraft, onMoveToDraft: () => movedToDraft = true),
      );
      await tester.tap(find.text('Move to Draft'));
      expect(movedToDraft, true);
    });

    testWidgets('unpublished row shows Move to Draft button', (tester) async {
      await tester.pumpWidget(buildTestWidget(unpublishedDraft));
      expect(find.text('Move to Draft'), findsOneWidget);
      expect(find.text('Publish to Store'), findsNothing);
    });

    testWidgets('calls onMoveToDraft when Move to Draft is tapped for unpublished', (tester) async {
      var movedToDraft = false;
      await tester.pumpWidget(
        buildTestWidget(unpublishedDraft, onMoveToDraft: () => movedToDraft = true),
      );
      await tester.tap(find.text('Move to Draft'));
      expect(movedToDraft, true);
    });
  });

  group('updating state', () {
    testWidgets('Publish button is disabled while updating', (tester) async {
      var tapped = false;
      await tester.pumpWidget(
        buildTestWidget(sampleDraft, isUpdating: true, onPublish: () => tapped = true),
      );

      // The button should be present but disabled.
      expect(find.text('Publish to Store'), findsOneWidget);
      await tester.tap(find.text('Publish to Store'));
      expect(tapped, false);
    });

    testWidgets('Move to Draft button is disabled while updating', (tester) async {
      var tapped = false;
      await tester.pumpWidget(
        buildTestWidget(publishedDraft, isUpdating: true, onMoveToDraft: () => tapped = true),
      );

      // The button should be present but disabled.
      expect(find.text('Move to Draft'), findsOneWidget);
      await tester.tap(find.text('Move to Draft'));
      expect(tapped, false);
    });

    testWidgets('Move to Draft button is disabled while updating for pending review', (
      tester,
    ) async {
      var tapped = false;
      await tester.pumpWidget(
        buildTestWidget(pendingDraft, isUpdating: true, onMoveToDraft: () => tapped = true),
      );

      expect(find.text('Move to Draft'), findsOneWidget);
      await tester.tap(find.text('Move to Draft'));
      expect(tapped, false);
    });

    testWidgets('Move to Draft button is disabled while updating for unpublished', (tester) async {
      var tapped = false;
      await tester.pumpWidget(
        buildTestWidget(unpublishedDraft, isUpdating: true, onMoveToDraft: () => tapped = true),
      );

      expect(find.text('Move to Draft'), findsOneWidget);
      await tester.tap(find.text('Move to Draft'));
      expect(tapped, false);
    });

    testWidgets('shows progress indicator while updating', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft, isUpdating: true));
      expect(find.byType(CircularProgressIndicator), findsOneWidget);
    });

    testWidgets('hides progress indicator when not updating', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft, isUpdating: false));
      expect(find.byType(CircularProgressIndicator), findsNothing);
    });
  });

  group('price editing', () {
    testWidgets('shows edit icon when onPriceChanged is provided', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft, onPriceChanged: (_) {}));
      expect(find.byIcon(Icons.edit), findsOneWidget);
    });

    testWidgets('hides edit icon when onPriceChanged is null', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.byIcon(Icons.edit), findsNothing);
    });

    testWidgets('hides edit icon while updating', (tester) async {
      await tester.pumpWidget(
        buildTestWidget(sampleDraft, onPriceChanged: (_) {}, isUpdating: true),
      );
      expect(find.byIcon(Icons.edit), findsNothing);
    });

    testWidgets('tapping edit icon shows text field with current price', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft, onPriceChanged: (_) {}));

      await tester.tap(find.byIcon(Icons.edit));
      await tester.pump();

      expect(find.byType(TextField), findsOneWidget);
      // The text field should be pre-filled with the current price.
      final textField = tester.widget<TextField>(find.byType(TextField));
      expect(textField.controller!.text, '12.99');
    });

    testWidgets('tapping check icon submits the new price', (tester) async {
      double? receivedPrice;
      await tester.pumpWidget(
        buildTestWidget(sampleDraft, onPriceChanged: (p) => receivedPrice = p),
      );

      // Enter edit mode.
      await tester.tap(find.byIcon(Icons.edit));
      await tester.pump();

      // Clear and type a new price.
      await tester.enterText(find.byType(TextField), '15.50');
      await tester.tap(find.byIcon(Icons.check));
      await tester.pump();

      expect(receivedPrice, 15.50);
      // Should exit edit mode — no more text field.
      expect(find.byType(TextField), findsNothing);
    });

    testWidgets('tapping close icon cancels editing', (tester) async {
      double? receivedPrice;
      await tester.pumpWidget(
        buildTestWidget(sampleDraft, onPriceChanged: (p) => receivedPrice = p),
      );

      // Enter edit mode.
      await tester.tap(find.byIcon(Icons.edit));
      await tester.pump();

      // Type a new price but cancel.
      await tester.enterText(find.byType(TextField), '99.99');
      await tester.tap(find.byIcon(Icons.close));
      await tester.pump();

      expect(receivedPrice, isNull);
      // Should exit edit mode and show original price.
      expect(find.byType(TextField), findsNothing);
      expect(find.text('\$12.99'), findsOneWidget);
    });

    testWidgets('submitting via keyboard calls onPriceChanged', (tester) async {
      double? receivedPrice;
      await tester.pumpWidget(
        buildTestWidget(sampleDraft, onPriceChanged: (p) => receivedPrice = p),
      );

      await tester.tap(find.byIcon(Icons.edit));
      await tester.pump();

      await tester.enterText(find.byType(TextField), '20.00');
      await tester.testTextInput.receiveAction(TextInputAction.done);
      await tester.pump();

      expect(receivedPrice, 20.00);
    });
  });

  group('name editing', () {
    testWidgets('shows edit name icon when onNameChanged is provided', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft, onNameChanged: (_) {}));
      // Find the edit icon with 'Edit name' tooltip.
      expect(find.byTooltip('Edit name'), findsOneWidget);
    });

    testWidgets('hides edit name icon when onNameChanged is null', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft));
      expect(find.byTooltip('Edit name'), findsNothing);
    });

    testWidgets('hides edit name icon while updating', (tester) async {
      await tester.pumpWidget(
        buildTestWidget(sampleDraft, onNameChanged: (_) {}, isUpdating: true),
      );
      expect(find.byTooltip('Edit name'), findsNothing);
    });

    testWidgets('tapping edit name icon shows text field with current name', (tester) async {
      await tester.pumpWidget(buildTestWidget(sampleDraft, onNameChanged: (_) {}));

      await tester.tap(find.byTooltip('Edit name'));
      await tester.pump();

      expect(find.byType(TextField), findsOneWidget);
      final textField = tester.widget<TextField>(find.byType(TextField));
      expect(textField.controller!.text, 'Test Bowl Cozy');
    });

    testWidgets('tapping check icon submits the new name', (tester) async {
      String? receivedName;
      await tester.pumpWidget(buildTestWidget(sampleDraft, onNameChanged: (n) => receivedName = n));

      // Enter edit mode.
      await tester.tap(find.byTooltip('Edit name'));
      await tester.pump();

      // Clear and type a new name.
      await tester.enterText(find.byType(TextField), 'Updated Bowl Cozy');
      await tester.tap(find.byTooltip('Save name'));
      await tester.pump();

      expect(receivedName, 'Updated Bowl Cozy');
      // Should exit edit mode — no more text field.
      expect(find.byType(TextField), findsNothing);
    });

    testWidgets('tapping close icon cancels name editing', (tester) async {
      String? receivedName;
      await tester.pumpWidget(buildTestWidget(sampleDraft, onNameChanged: (n) => receivedName = n));

      // Enter edit mode.
      await tester.tap(find.byTooltip('Edit name'));
      await tester.pump();

      // Type a new name but cancel.
      await tester.enterText(find.byType(TextField), 'Cancelled Name');
      // Find the Cancel button (close icon) — use tooltip to disambiguate.
      await tester.tap(find.byTooltip('Cancel'));
      await tester.pump();

      expect(receivedName, isNull);
      // Should exit edit mode and show original name.
      expect(find.byType(TextField), findsNothing);
      expect(find.text('Test Bowl Cozy'), findsOneWidget);
    });

    testWidgets('submitting via keyboard calls onNameChanged', (tester) async {
      String? receivedName;
      await tester.pumpWidget(buildTestWidget(sampleDraft, onNameChanged: (n) => receivedName = n));

      await tester.tap(find.byTooltip('Edit name'));
      await tester.pump();

      await tester.enterText(find.byType(TextField), 'Keyboard Name');
      await tester.testTextInput.receiveAction(TextInputAction.done);
      await tester.pump();

      expect(receivedName, 'Keyboard Name');
    });

    testWidgets('does not submit empty name', (tester) async {
      String? receivedName;
      await tester.pumpWidget(buildTestWidget(sampleDraft, onNameChanged: (n) => receivedName = n));

      await tester.tap(find.byTooltip('Edit name'));
      await tester.pump();

      // Clear the field and try to submit.
      await tester.enterText(find.byType(TextField), '');
      await tester.tap(find.byTooltip('Save name'));
      await tester.pump();

      // Should not have called the callback.
      expect(receivedName, isNull);
      // Should still be in edit mode.
      expect(find.byType(TextField), findsOneWidget);
    });
  });
}
