import 'package:meta/meta.dart';

/// 入出庫区分。
enum InventoryMovementType {
  receipt,
  issue,
  adjustment,
}

extension InventoryMovementTypeX on InventoryMovementType {
  String get displayName {
    switch (this) {
      case InventoryMovementType.receipt:
        return '入庫';
      case InventoryMovementType.issue:
        return '出庫';
      case InventoryMovementType.adjustment:
        return '棚卸/調整';
    }
  }

  /// 在庫増減に与える係数。
  int get deltaSign {
    switch (this) {
      case InventoryMovementType.receipt:
        return 1;
      case InventoryMovementType.issue:
        return -1;
      case InventoryMovementType.adjustment:
        return 1; // 調整は quantityDelta をそのまま使うため符号 1 とする
    }
  }
}

@immutable
class InventoryMovement {
  const InventoryMovement({
    required this.id,
    required this.productId,
    required this.productNameSnapshot,
    required this.type,
    required this.quantity,
    required this.quantityDelta,
    required this.createdAt,
    this.reference,
    this.notes,
  });

  final String id;
  final String productId;
  final String productNameSnapshot;
  final InventoryMovementType type;
  final int quantity;
  final int quantityDelta;
  final DateTime createdAt;
  final String? reference;
  final String? notes;

  Map<String, dynamic> toMap() => {
        'id': id,
        'product_id': productId,
        'product_name_snapshot': productNameSnapshot,
        'movement_type': type.name,
        'quantity': quantity,
        'quantity_delta': quantityDelta,
        'reference': reference,
        'notes': notes,
        'created_at': createdAt.toIso8601String(),
      };

  factory InventoryMovement.fromMap(Map<String, dynamic> map) {
    InventoryMovementType parseType(String? value) {
      return InventoryMovementType.values.firstWhere(
        (type) => type.name == value,
        orElse: () => InventoryMovementType.adjustment,
      );
    }

    return InventoryMovement(
      id: map['id'] as String,
      productId: map['product_id'] as String,
      productNameSnapshot: map['product_name_snapshot'] as String? ?? '-',
      type: parseType(map['movement_type'] as String?),
      quantity: map['quantity'] as int? ?? 0,
      quantityDelta: map['quantity_delta'] as int? ?? 0,
      reference: map['reference'] as String?,
      notes: map['notes'] as String?,
      createdAt: DateTime.parse(map['created_at'] as String),
    );
  }
}

@immutable
class InventorySummary {
  const InventorySummary({
    required this.productId,
    required this.productName,
    required this.stockQuantity,
    this.category,
    this.defaultUnitPrice,
    this.lastMovementAt,
  });

  final String productId;
  final String productName;
  final int stockQuantity;
  final String? category;
  final int? defaultUnitPrice;
  final DateTime? lastMovementAt;

  InventorySummary copyWith({
    int? stockQuantity,
    DateTime? lastMovementAt,
  }) {
    return InventorySummary(
      productId: productId,
      productName: productName,
      stockQuantity: stockQuantity ?? this.stockQuantity,
      category: category,
      defaultUnitPrice: defaultUnitPrice,
      lastMovementAt: lastMovementAt ?? this.lastMovementAt,
    );
  }
}
