import 'package:hl_lieferservice/dto/article.dart';

import 'component.dart';

class Article {
  Article({
    required this.name,
    required this.articleNumber,
    required this.amount,
    required this.internalId,
    required this.price,
    required this.tax,
    required this.scannable,
    required this.scannedAmount,
    required this.scannedRemovedAmount,
    required this.isParent,
    this.components = const [],
    this.scannedDate,
    this.removeNoteId,
    this.warehouseNr,
    this.warehouseName,
  });

  final String name;
  final String articleNumber;
  final int internalId;
  final bool isParent;
  final List<Component> components;
  final String? warehouseNr;
  final String? warehouseName;

  int amount;
  double price;
  double tax;
  bool scannable;
  DateTime? scannedDate;
  String? removeNoteId;
  int scannedAmount;
  int scannedRemovedAmount;

  double getGrossPrice() {
    return price * amount * ((100 + tax) / 100);
  }

  double getGrossPriceScanned() {
    return price * scannedAmount * ((100 + tax) / 100);
  }

  /// Whether this article is fully scanned.
  ///
  /// For parent articles (Stückliste): delegates to components — all must be
  /// individually scanned.  For regular articles: the classic amount check.
  bool get isFullyScanned {
    if (isParent && components.isNotEmpty) {
      return components.every((c) => c.isFullyScanned);
    }
    return scannedAmount + scannedRemovedAmount >= amount;
  }

  /// Find a component by its article number, or `null` if none matches.
  Component? findComponent(String articleNumber) {
    for (final c in components) {
      if (c.articleNumber == articleNumber) return c;
    }
    return null;
  }

  /// Whether this article *or* any of its components carries [articleNumber].
  bool hasArticleNumber(String articleNumber) {
    if (this.articleNumber == articleNumber) return true;
    return components.any((c) => c.articleNumber == articleNumber);
  }

  bool unscanned() {
    if (isParent && components.isNotEmpty) {
      return components.every((c) => c.scannedAmount == 0);
    }
    return scannedAmount == 0;
  }

  int getScannedAmount() {
    return scannedAmount;
  }

  factory Article.fromDTO(ArticleDTO dto) {
    return Article(
      name: dto.name,
      scannedAmount: int.parse(
        dto.scannedAmount != "" ? dto.scannedAmount : "0",
      ),
      scannedRemovedAmount: int.tryParse(dto.scannedRemovedAmount) ?? 0,
      removeNoteId: dto.removeNoteId,
      internalId: int.parse(dto.internalId),
      articleNumber: dto.articleNr,
      amount: int.parse(dto.quantity == "" ? "0" : dto.quantity),
      price: double.parse(dto.price == "" ? "0.0" : dto.price),
      scannable: dto.scannable,
      tax: double.parse(dto.taxRate == "" ? "19" : dto.taxRate),
      isParent: dto.isParent,
      components: dto.components?.map(Component.fromDTO).toList() ?? [],
      warehouseNr: dto.warehouseNr?.isEmpty ?? true ? null : dto.warehouseNr,
      warehouseName:
          dto.warehouseName?.isEmpty ?? true ? null : dto.warehouseName,
    );
  }
}
