import 'package:feature_inventory/feature_inventory.dart';
import 'package:feature_orders/feature_orders.dart';
import 'package:feature_wordpress/feature_wordpress.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:kell_web/dashboard/application/dashboard_controller.dart';
import 'package:kell_web/dashboard/application/get_dashboard_summary.dart';
import 'package:kell_web/dashboard/domain/dashboard_summary.dart';

// ── Tiny stub repositories for testing ─────────────────────────────────────

class _StubInventoryRepository implements InventoryRepository {
  final List<InventoryItem> items;
  _StubInventoryRepository([this.items = const []]);

  @override
  Future<List<InventoryItem>> getInventoryItems() async => items;

  @override
  Future<InventoryAdjustmentResult> adjustQuantity(String id, int delta, String reason) =>
      throw UnimplementedError();

  @override
  Future<InventoryAdjustmentResult> setQuantity(String id, int quantity, String reason) =>
      throw UnimplementedError();

  @override
  Future<InventoryItem> createItem(InventoryItem item) => throw UnimplementedError();

  @override
  Future<InventoryItem> updateItem(InventoryItem item) => throw UnimplementedError();

  @override
  Future<InventoryAdjustmentResult> updateItemImage(String id, String imageUrl) =>
      throw UnimplementedError();
}

class _StubProductPublishingRepository implements ProductPublishingRepository {
  final List<ProductDraft> drafts;
  _StubProductPublishingRepository([this.drafts = const []]);

  @override
  Future<List<ProductDraft>> getProductDrafts() async => drafts;

  @override
  Future<ProductDraft> publishDraft(String id) => throw UnimplementedError();

  @override
  Future<ProductDraft> updateProductStatus(String id, PublishStatus status) =>
      throw UnimplementedError();

  @override
  Future<ProductDraft> updateProductPrice(String id, double price) => throw UnimplementedError();

  @override
  Future<ProductDraft> updateProductName(String id, String name) => throw UnimplementedError();

  @override
  Future<ProductDraft> updateProductDescription(String id, String description) =>
      throw UnimplementedError();

  @override
  Future<ProductDraft> updateProductCategory(String id, String category) =>
      throw UnimplementedError();
}

class _StubOrdersRepository implements OrdersRepository {
  final List<Order> orders;
  _StubOrdersRepository([this.orders = const []]);

  @override
  Future<List<Order>> getOrders() async => orders;

  @override
  Future<OrderActionResult> updateOrderStatus(String id, OrderStatus newStatus) =>
      throw UnimplementedError();

  @override
  Future<OrderActionResult> addOrderNote(String id, String note) => throw UnimplementedError();

  @override
  Future<OrderActionResult> createOrder(Order order) => throw UnimplementedError();
}

class _FailingInventoryRepository implements InventoryRepository {
  @override
  Future<List<InventoryItem>> getInventoryItems() => throw Exception('network error');

  @override
  Future<InventoryAdjustmentResult> adjustQuantity(String id, int delta, String reason) =>
      throw UnimplementedError();

  @override
  Future<InventoryAdjustmentResult> setQuantity(String id, int quantity, String reason) =>
      throw UnimplementedError();

  @override
  Future<InventoryItem> createItem(InventoryItem item) => throw UnimplementedError();

  @override
  Future<InventoryItem> updateItem(InventoryItem item) => throw UnimplementedError();

  @override
  Future<InventoryAdjustmentResult> updateItemImage(String id, String imageUrl) =>
      throw UnimplementedError();
}

// ── Shared test helpers ────────────────────────────────────────────────────

final _baseDate = DateTime(2026, 7, 1);

InventoryItem _inv({
  required String id,
  required String sku,
  required String name,
  required int quantityOnHand,
  required double unitPrice,
  required InventoryStatus status,
  int reorderPoint = 5,
}) {
  return InventoryItem(
    id: id,
    sku: sku,
    name: name,
    description: '',
    imageUrl: '',
    category: 'Test',
    quantityOnHand: quantityOnHand,
    unitPrice: unitPrice,
    reorderPoint: reorderPoint,
    status: status,
    lastUpdated: _baseDate,
  );
}

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

void main() {
  group('DashboardController', () {
    test('starts with empty summary and not loading', () {
      final controller = DashboardController(
        GetDashboardSummary(
          inventoryRepository: _StubInventoryRepository(),
          productPublishingRepository: _StubProductPublishingRepository(),
          ordersRepository: _StubOrdersRepository(),
        ),
      );

      expect(controller.isLoading, false);
      expect(controller.summary, DashboardSummary.empty);
      expect(controller.error, isNull);
    });

    test('load() sets isLoading then populates summary', () async {
      final inventoryItems = [
        _inv(
          id: '1',
          sku: 'A',
          name: 'A',
          quantityOnHand: 10,
          unitPrice: 5.0,
          status: InventoryStatus.inStock,
        ),
        _inv(
          id: '2',
          sku: 'B',
          name: 'B',
          quantityOnHand: 2,
          unitPrice: 5.0,
          status: InventoryStatus.lowStock,
        ),
      ];

      final controller = DashboardController(
        GetDashboardSummary(
          inventoryRepository: _StubInventoryRepository(inventoryItems),
          productPublishingRepository: _StubProductPublishingRepository(),
          ordersRepository: _StubOrdersRepository(),
        ),
      );

      // Track notification sequence.
      final loadingStates = <bool>[];
      controller.addListener(() => loadingStates.add(controller.isLoading));

      await controller.load();

      // First notification: isLoading = true, second: isLoading = false.
      expect(loadingStates, [true, false]);
      expect(controller.isLoading, false);
      expect(controller.error, isNull);
      expect(controller.summary.totalProducts, 2);
      expect(controller.summary.inStock, 1);
      expect(controller.summary.lowStock, 1);
    });

    test('load() captures error and clears isLoading', () async {
      final controller = DashboardController(
        GetDashboardSummary(
          inventoryRepository: _FailingInventoryRepository(),
          productPublishingRepository: _StubProductPublishingRepository(),
          ordersRepository: _StubOrdersRepository(),
        ),
      );

      await controller.load();

      expect(controller.isLoading, false);
      expect(controller.error, isNotNull);
      // Summary should remain empty on error.
      expect(controller.summary, DashboardSummary.empty);
    });

    test('load() aggregates data from all three repositories', () async {
      final inventoryItems = [
        _inv(
          id: '1',
          sku: 'A',
          name: 'A',
          quantityOnHand: 10,
          unitPrice: 5.0,
          status: InventoryStatus.inStock,
        ),
      ];

      final drafts = [
        ProductDraft(
          id: '1',
          name: 'Draft',
          description: '',
          price: 10,
          sku: 'D',
          category: 'Cat',
          imageUrl: '',
          status: PublishStatus.draft,
          lastModified: DateTime(2026),
        ),
      ];

      final orders = [
        Order(
          id: '1',
          customerName: 'Test',
          customerEmail: 'test@test.com',
          orderDate: DateTime(2026),
          status: OrderStatus.pending,
          items: const [OrderItem(productName: 'X', sku: 'X', quantity: 1, unitPrice: 10.0)],
          shippingAddress: '',
        ),
      ];

      final controller = DashboardController(
        GetDashboardSummary(
          inventoryRepository: _StubInventoryRepository(inventoryItems),
          productPublishingRepository: _StubProductPublishingRepository(drafts),
          ordersRepository: _StubOrdersRepository(orders),
        ),
      );

      await controller.load();

      expect(controller.summary.totalProducts, 1);
      expect(controller.summary.inStock, 1);
      expect(controller.summary.draftProducts, 1);
      expect(controller.summary.totalOrders, 1);
      expect(controller.summary.pendingOrders, 1);
    });

    test('subsequent load() clears previous error', () async {
      final failingController = DashboardController(
        GetDashboardSummary(
          inventoryRepository: _FailingInventoryRepository(),
          productPublishingRepository: _StubProductPublishingRepository(),
          ordersRepository: _StubOrdersRepository(),
        ),
      );

      await failingController.load();
      expect(failingController.error, isNotNull);

      // Create a new controller with working repos to verify error clearing pattern.
      final workingController = DashboardController(
        GetDashboardSummary(
          inventoryRepository: _StubInventoryRepository(),
          productPublishingRepository: _StubProductPublishingRepository(),
          ordersRepository: _StubOrdersRepository(),
        ),
      );

      await workingController.load();
      expect(workingController.error, isNull);
    });
  });
}
