import 'package:dartz/dartz.dart';
import '../../../core/errors/failures.dart';
import '../../../domain/entities/company_hierarchy.dart';
import '../../../models/company_model.dart';
import '../../repositories/company_repository.dart';
import '../base_usecase.dart';

/// 회사 계층 구조 조회 파라미터
class GetCompanyHierarchyParams {
  final bool includeInactive;

  const GetCompanyHierarchyParams({
    this.includeInactive = false,
  });
}

/// 회사 계층 구조 조회 UseCase
class GetCompanyHierarchyUseCase extends UseCase<CompanyHierarchy, GetCompanyHierarchyParams> {
  // 레포지토리 기반으로 마이그레이션
  final CompanyRepository _companyRepository;

  GetCompanyHierarchyUseCase(this._companyRepository);

  @override
  Future<Either<Failure, CompanyHierarchy>> call(GetCompanyHierarchyParams params) async {
    try {
      // 레포지토리에서 전체 회사(계층 구성용) 조회
      final companiesEither = await _companyRepository.getCompanyHierarchy(
        includeInactive: params.includeInactive,
      );
      
      final hierarchy = companiesEither.fold(
        (failure) => throw failure,
        (companies) => _buildHierarchy(companies),
      );
      
      return Right(hierarchy);
    } on ServerFailure catch (e) {
      return Left(ServerFailure(
        message: e.message,
        originalError: e,
      ));
    } catch (e) {
      return Left(UnknownFailure(
        message: '회사 계층 구조 조회 중 오류가 발생했습니다.',
        originalError: e,
      ));
    }
  }

  /// 회사 목록을 계층 구조로 변환
  CompanyHierarchy _buildHierarchy(List<Company> companies) {
    // 루트 회사들 찾기 (parent_company_id가 null인 회사들)
    final rootCompanies = companies.where((c) => c.parentCompanyId == null).toList();
    
    // 계층 구조 생성
    final children = rootCompanies.map((company) => 
      _buildCompanyNode(company, companies, 0)
    ).toList();
    
    return CompanyHierarchy(
      id: '0',
      name: 'Root',
      children: children,
      totalDescendants: _countDescendants(children),
    );
  }
  
  /// 회사 노드 생성 (재귀)
  CompanyHierarchy _buildCompanyNode(
    Company company,
    List<Company> allCompanies,
    int level,
  ) {
    // 자식 회사들 찾기
    final childCompanies = allCompanies
        .where((c) => c.parentCompanyId == company.id)
        .toList();
    
    // 자식 노드들 생성
    final children = childCompanies
        .map((child) => _buildCompanyNode(child, allCompanies, level + 1))
        .toList();
    
    return CompanyHierarchy(
      id: company.id.toString(),
      name: company.name,
      parentId: company.parentCompanyId?.toString(),
      children: children,
      level: level,
      fullPath: _buildPath(company, allCompanies),
      totalDescendants: _countDescendants(children),
    );
  }
  
  /// 경로 생성
  String _buildPath(Company company, List<Company> allCompanies) {
    final path = <String>[company.name];
    Company? current = company;
    
    while (current?.parentCompanyId != null) {
      final parent = allCompanies.firstWhere(
        (c) => c.id == current!.parentCompanyId,
        orElse: () => Company(
          id: 0,
          name: '',
        ),
      );
      
      if (parent.id == 0) break;
      
      path.insert(0, parent.name);
      current = parent;
    }
    
    return '/${path.join('/')}';
  }
  
  /// 자손 수 계산
  int _countDescendants(List<CompanyHierarchy> children) {
    int count = children.length;
    
    for (final child in children) {
      count += child.totalDescendants;
    }
    
    return count;
  }
}
