// This file covers domain model tests for the feature_orders package.
import 'package:flutter_test/flutter_test.dart';

import 'package:feature_orders/feature_orders.dart';

void main() {
  // ── Order domain model ─────────────────────────────────────────────────

  group('Order', () {
    final baseOrder = Order(
      id: 'KC-0001',
      customerName: 'Test Customer',
      customerEmail: 'test@example.com',
      customerPhone: '555-0100',
      orderDate: DateTime(2026, 1, 1),
      status: OrderStatus.pending,
      items: const [
        OrderItem(productName: 'Widget', sku: 'WG-001', quantity: 2, unitPrice: 10.00),
        OrderItem(productName: 'Gadget', sku: 'GD-002', quantity: 1, unitPrice: 5.50),
      ],
      shippingAddress: '1 Test St, Test City, TC 00000',
      notes: 'Internal note',
      orderNotes: const ['Customer note 1'],
    );

    test('total is sum of all line totals', () {
      // 2 * 10.00 + 1 * 5.50 = 25.50
      expect(baseOrder.total, closeTo(25.50, 0.001));
    });

    test('itemCount is sum of all quantities', () {
      // 2 + 1 = 3
      expect(baseOrder.itemCount, 3);
    });

    test('copyWith replaces status', () {
      final updated = baseOrder.copyWith(status: OrderStatus.processing);
      expect(updated.status, OrderStatus.processing);
      expect(updated.id, baseOrder.id);
      expect(updated.customerName, baseOrder.customerName);
    });

    test('copyWith replaces orderNotes', () {
      final updated = baseOrder.copyWith(orderNotes: ['New note']);
      expect(updated.orderNotes, ['New note']);
      expect(updated.status, baseOrder.status);
    });

    test('copyWith replaces notes', () {
      final updated = baseOrder.copyWith(notes: 'Updated internal note');
      expect(updated.notes, 'Updated internal note');
    });

    test('copyWith replaces customerPhone', () {
      final updated = baseOrder.copyWith(customerPhone: '555-9999');
      expect(updated.customerPhone, '555-9999');
    });

    test('copyWith with no arguments returns equivalent order', () {
      final copy = baseOrder.copyWith();
      expect(copy.id, baseOrder.id);
      expect(copy.customerName, baseOrder.customerName);
      expect(copy.status, baseOrder.status);
      expect(copy.orderNotes, baseOrder.orderNotes);
    });

    test('default orderNotes is empty list', () {
      final order = Order(
        id: 'KC-0002',
        customerName: 'Minimal',
        customerEmail: 'min@example.com',
        orderDate: DateTime(2026, 1, 1),
        status: OrderStatus.pending,
        items: const [],
        shippingAddress: '',
      );
      expect(order.orderNotes, isEmpty);
    });

    test('customerPhone defaults to null', () {
      final order = Order(
        id: 'KC-0003',
        customerName: 'No Phone',
        customerEmail: 'nophone@example.com',
        orderDate: DateTime(2026, 1, 1),
        status: OrderStatus.pending,
        items: const [],
        shippingAddress: '',
      );
      expect(order.customerPhone, isNull);
    });

    test('notes defaults to null', () {
      final order = Order(
        id: 'KC-0004',
        customerName: 'No Notes',
        customerEmail: 'nonotes@example.com',
        orderDate: DateTime(2026, 1, 1),
        status: OrderStatus.pending,
        items: const [],
        shippingAddress: '',
      );
      expect(order.notes, isNull);
    });

    test('total is zero for empty items list', () {
      final order = Order(
        id: 'KC-0005',
        customerName: 'Empty',
        customerEmail: 'empty@example.com',
        orderDate: DateTime(2026, 1, 1),
        status: OrderStatus.pending,
        items: const [],
        shippingAddress: '',
      );
      expect(order.total, 0.0);
      expect(order.itemCount, 0);
    });
  });

  // ── OrderItem ──────────────────────────────────────────────────────────

  group('OrderItem', () {
    test('lineTotal is quantity * unitPrice', () {
      const item = OrderItem(productName: 'Test', sku: 'T-001', quantity: 3, unitPrice: 7.50);
      expect(item.lineTotal, closeTo(22.50, 0.001));
    });

    test('lineTotal is zero for zero quantity', () {
      const item = OrderItem(productName: 'Test', sku: 'T-001', quantity: 0, unitPrice: 10.00);
      expect(item.lineTotal, 0.0);
    });
  });

  // ── OrderStatus ────────────────────────────────────────────────────────

  group('OrderStatus', () {
    test('all statuses are distinct', () {
      final statuses = OrderStatus.values.toSet();
      expect(statuses.length, OrderStatus.values.length);
    });

    test('contains expected values', () {
      expect(OrderStatus.values, contains(OrderStatus.pending));
      expect(OrderStatus.values, contains(OrderStatus.processing));
      expect(OrderStatus.values, contains(OrderStatus.shipped));
      expect(OrderStatus.values, contains(OrderStatus.delivered));
      expect(OrderStatus.values, contains(OrderStatus.cancelled));
    });
  });

  // ── OrderActionResult ──────────────────────────────────────────────────

  group('OrderActionResult', () {
    final sampleOrder = Order(
      id: 'KC-0001',
      customerName: 'Test',
      customerEmail: 'test@example.com',
      orderDate: DateTime(2026, 1, 1),
      status: OrderStatus.pending,
      items: const [],
      shippingAddress: '',
    );

    test('success result has success=true and updatedOrder set', () {
      final result = OrderActionResult.success(sampleOrder);
      expect(result.success, true);
      expect(result.updatedOrder, sampleOrder);
      expect(result.errorMessage, isNull);
    });

    test('failure result has success=false and errorMessage set', () {
      const result = OrderActionResult.failure('Something went wrong.');
      expect(result.success, false);
      expect(result.updatedOrder, isNull);
      expect(result.errorMessage, 'Something went wrong.');
    });
  });

  // ── Barrel export smoke test ───────────────────────────────────────────

  test('barrel export exposes Order', () {
    final order = Order(
      id: 'test',
      customerName: 'Test',
      customerEmail: 'test@test.com',
      orderDate: DateTime(2026, 1, 1),
      status: OrderStatus.pending,
      items: const [],
      shippingAddress: '123 Test St',
    );
    expect(order.id, 'test');
  });
}
