import 'package:freezed_annotation/freezed_annotation.dart';

part 'company_hierarchy.freezed.dart';

/// Company 계층 구조 도메인 엔티티
@freezed
class CompanyHierarchy with _$CompanyHierarchy {
  const CompanyHierarchy._();

  const factory CompanyHierarchy({
    required String id,
    required String name,
    String? parentId,
    String? parentName,
    @Default([]) List<CompanyHierarchy> children,
    @Default(0) int level,
    @Default('') String fullPath,
    @Default(false) bool isExpanded,
    @Default(0) int totalDescendants,
  }) = _CompanyHierarchy;

  /// 계층 구조에서 특정 회사 찾기
  CompanyHierarchy? findCompany(String companyId) {
    if (id == companyId) {
      return this;
    }
    
    for (final child in children) {
      final found = child.findCompany(companyId);
      if (found != null) {
        return found;
      }
    }
    
    return null;
  }

  /// 모든 자손 회사 ID 목록 가져오기
  List<String> getAllDescendantIds() {
    final ids = <String>[];
    
    for (final child in children) {
      ids.add(child.id);
      ids.addAll(child.getAllDescendantIds());
    }
    
    return ids;
  }

  /// 특정 회사가 자손인지 확인
  bool hasDescendant(String companyId) {
    return getAllDescendantIds().contains(companyId);
  }

  /// 계층 구조의 최대 깊이 계산
  int getMaxDepth() {
    if (children.isEmpty) {
      return level;
    }
    
    return children
        .map((child) => child.getMaxDepth())
        .reduce((max, depth) => depth > max ? depth : max);
  }

  /// 순환 참조 검증
  bool wouldCreateCycle(String newParentId) {
    // 자기 자신을 부모로 설정하려는 경우
    if (id == newParentId) {
      return true;
    }
    
    // 자손을 부모로 설정하려는 경우
    if (hasDescendant(newParentId)) {
      return true;
    }
    
    return false;
  }

  /// 계층 경로 생성
  String buildPath(String separator) {
    final parts = fullPath.split('/').where((p) => p.isNotEmpty).toList();
    return parts.join(separator);
  }

  /// 평면 리스트로 변환 (트리 구조 → 플랫 리스트)
  List<CompanyHierarchy> flatten() {
    final flatList = <CompanyHierarchy>[this];
    
    for (final child in children) {
      flatList.addAll(child.flatten());
    }
    
    return flatList;
  }

  /// 계층 구조 통계
  Map<String, dynamic> getStatistics() {
    final flat = flatten();
    return {
      'totalCompanies': flat.length,
      'maxDepth': getMaxDepth(),
      'directChildren': children.length,
      'totalDescendants': totalDescendants,
      'levels': _getLevelDistribution(flat),
    };
  }

  Map<int, int> _getLevelDistribution(List<CompanyHierarchy> companies) {
    final distribution = <int, int>{};
    
    for (final company in companies) {
      distribution[company.level] = (distribution[company.level] ?? 0) + 1;
    }
    
    return distribution;
  }
}

/// 계층 구조 검증 결과
@freezed
class HierarchyValidationResult with _$HierarchyValidationResult {
  const factory HierarchyValidationResult({
    required bool isValid,
    @Default('') String message,
    @Default([]) List<String> errors,
    @Default([]) List<String> warnings,
  }) = _HierarchyValidationResult;

  factory HierarchyValidationResult.valid() => const HierarchyValidationResult(
    isValid: true,
    message: 'Hierarchy is valid',
  );

  factory HierarchyValidationResult.invalid({
    required String message,
    List<String> errors = const [],
    List<String> warnings = const [],
  }) => HierarchyValidationResult(
    isValid: false,
    message: message,
    errors: errors,
    warnings: warnings,
  );
}