import 'package:flutter/foundation.dart';
import 'package:injectable/injectable.dart';
import 'package:dartz/dartz.dart';
import 'package:superport/core/constants/app_constants.dart';
import 'package:superport/core/errors/exceptions.dart';
import 'package:superport/core/errors/failures.dart';
import 'package:superport/data/datasources/remote/company_remote_datasource.dart';
import 'package:superport/data/models/common/paginated_response.dart';
import 'package:superport/data/models/company/company_dto.dart';
import 'package:superport/data/models/company/company_list_dto.dart';
// Branch DTO는 더 이상 사용하지 않음 (계층형 Company 구조로 변경)
import 'package:superport/models/company_model.dart';
import 'package:superport/models/company_item_model.dart';
import 'package:superport/models/address_model.dart';

@lazySingleton
class CompanyService {
  final CompanyRemoteDataSource _remoteDataSource;
  
  CompanyService(this._remoteDataSource);

  // 회사 목록 조회
  Future<PaginatedResponse<Company>> getCompanies({
    int page = 1,
    int perPage = AppConstants.companyPageSize,
    String? search,
    bool? isActive,
    bool includeInactive = false,
  }) async {
    try {
      // 🔧 백엔드 버그 우회: 검색 시에는 is_active 파라미터 제거
      // search + is_active 조합에서 빈 결과 반환 버그 존재
      final effectiveIsActive = search != null && search.isNotEmpty 
          ? null  // 검색 시에는 is_active 필터 제거
          : (isActive ?? !includeInactive); // 일반 목록 조회는 기존 로직 유지
          
      final response = await _remoteDataSource.getCompanies(
        page: page,
        perPage: perPage,
        search: search,
        isActive: effectiveIsActive,
      );

      return PaginatedResponse<Company>(
        items: response.items.map((dto) => _convertListDtoToCompany(dto)).toList(),
        page: response.page,
        size: response.size,
        totalElements: response.totalElements,
        totalPages: response.totalPages,
        first: response.first,
        last: response.last,
      );
    } on ApiException catch (e) {
      debugPrint('[CompanyService] ApiException: ${e.message}');
      throw ServerFailure(message: e.message);
    } catch (e, stackTrace) {
      debugPrint('[CompanyService] Error loading companies: $e');
      debugPrint('[CompanyService] Stack trace: $stackTrace');
      throw ServerFailure(message: 'Failed to fetch company list: $e');
    }
  }

  // 회사 생성
  Future<Company> createCompany(Company company) async {
    try {
      final request = CompanyRequestDto(
        name: company.name,
        address: company.address.toString(),
        contactName: company.contactName ?? '',
        contactPhone: company.contactPhone ?? '',
        contactEmail: company.contactEmail ?? '',
        isPartner: company.isPartner,
        isCustomer: company.isCustomer,
        parentCompanyId: company.parentCompanyId,
        remark: company.remark,
      );

      debugPrint('[CompanyService] Creating company with request: ${request.toJson()}');
      final response = await _remoteDataSource.createCompany(request);
      debugPrint('[CompanyService] Company created with ID: ${response.id}');
      return _convertResponseToCompany(response);
    } on ApiException catch (e) {
      debugPrint('[CompanyService] ApiException during company creation: ${e.message}');
      throw ServerFailure(message: e.message);
    } catch (e, stackTrace) {
      debugPrint('[CompanyService] Unexpected error during company creation: $e');
      debugPrint('[CompanyService] Stack trace: $stackTrace');
      throw ServerFailure(message: 'Failed to create company: $e');
    }
  }

  // 회사 상세 조회
  Future<Company> getCompanyDetail(int id) async {
    try {
      final response = await _remoteDataSource.getCompanyDetail(id);
      return _convertResponseToCompany(response);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to fetch company detail: $e');
    }
  }

  // 회사와 자회사 정보 함께 조회 (계층형 구조)
  Future<Company> getCompanyWithChildren(int id) async {
    try {
      final response = await _remoteDataSource.getCompanyWithChildren(id);
      final company = _convertResponseToCompany(response.company);
      // TODO: children 정보는 필요시 별도 처리 
      
      return company;
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to fetch company with children: $e');
    }
  }

  // 회사 수정
  Future<Company> updateCompany(int id, Company company) async {
    try {
      final request = CompanyUpdateRequestDto(
        name: company.name,
        address: company.address.toString(),
        contactName: company.contactName,
        contactPhone: company.contactPhone,
        contactEmail: company.contactEmail,
        isPartner: company.isPartner,
        isCustomer: company.isCustomer,
        parentCompanyId: company.parentCompanyId,
        remark: company.remark,
      );

      final response = await _remoteDataSource.updateCompany(id, request);
      return _convertResponseToCompany(response);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to update company: $e');
    }
  }

  // 회사 삭제
  Future<void> deleteCompany(int id) async {
    try {
      await _remoteDataSource.deleteCompany(id);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to delete company: $e');
    }
  }

  // 회사명 목록 조회 (드롭다운용)
  Future<List<CompanyNameDto>> getCompanyNames() async {
    try {
      return await _remoteDataSource.getCompanyNames();
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to fetch company names: $e');
    }
  }

  // DEPRECATED: 지점 관련 메서드들 (계층형 Company 구조로 대체)
  @Deprecated('계층형 Company 구조로 대체되었습니다. createCompany를 사용하세요.')
  Future<Company> createBranch(int companyId, Company childCompany) async {
    // TODO: parentCompanyId를 설정하여 자회사로 생성
    final companyWithParent = childCompany.copyWith(parentCompanyId: companyId);
    return createCompany(companyWithParent);
  }

  // DEPRECATED: 더 이상 사용하지 않는 Branch 관련 메서드들
  /*
  Future<Branch> getBranchDetail(int companyId, int branchId) async {
    try {
      final response = await _remoteDataSource.getBranchDetail(companyId, branchId);
      return _convertBranchResponseToBranch(response);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to fetch branch detail: $e');
    }
  }

  Future<Branch> updateBranch(int companyId, int branchId, Branch branch) async {
    try {
      final request = UpdateBranchRequest(
        branchName: branch.name,
        address: branch.address.toString(),
        phone: branch.contactPhone,
        managerName: branch.contactName,
        managerPhone: branch.contactPhone,
        remark: branch.remark,
      );

      final response = await _remoteDataSource.updateBranch(companyId, branchId, request);
      return _convertBranchResponseToBranch(response);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to update branch: $e');
    }
  }

  Future<void> deleteBranch(int companyId, int branchId) async {
    try {
      await _remoteDataSource.deleteBranch(companyId, branchId);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to delete branch: $e');
    }
  }

  Future<List<Branch>> getCompanyBranches(int companyId) async {
    try {
      final dtoList = await _remoteDataSource.getCompanyBranches(companyId);
      return dtoList.map((dto) => _convertBranchDtoToBranch(dto)).toList();
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to fetch company branches: $e');
    }
  }
  */

  // 회사-지점 전체 정보 조회
  Future<List<CompanyWithChildren>> getCompaniesWithBranches() async {
    try {
      return await _remoteDataSource.getCompaniesWithBranches();
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to fetch companies with branches: $e');
    }
  }

  // 회사명 중복 확인
  Future<bool> checkDuplicateCompany(String name) async {
    try {
      return await _remoteDataSource.checkDuplicateCompany(name);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to check duplicate: $e');
    }
  }

  // 회사 검색
  Future<List<Company>> searchCompanies(String query) async {
    try {
      final dtoList = await _remoteDataSource.searchCompanies(query);
      return dtoList.map((dto) => _convertListDtoToCompany(dto)).toList();
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to search companies: $e');
    }
  }

  // 회사 활성 상태 변경
  Future<void> updateCompanyStatus(int id, bool isActive) async {
    try {
      await _remoteDataSource.updateCompanyStatus(id, isActive);
    } on ApiException catch (e) {
      throw ServerFailure(message: e.message);
    } catch (e) {
      throw ServerFailure(message: 'Failed to update company status: $e');
    }
  }
  
  // 회사 목록과 지점 정보를 함께 조회 (플랫 데이터를 그룹화)
  Future<List<Company>> getCompaniesWithBranchesFlat() async {
    try {
      final flatData = await _remoteDataSource.getCompanyBranchesFlat();
      
      // 회사별로 데이터 그룹화
      final Map<int, List<Branch>> companyBranchesMap = {};
      final Map<int, String> companyNamesMap = {};
      final Map<int, List<CompanyType>> companyTypesMap = {};
      final Map<int, bool> companyIsPartnerMap = {};
      final Map<int, bool> companyIsCustomerMap = {};
      
      for (final item in flatData) {
        companyNamesMap[item.companyId] = item.companyName;
        
        // 첫 번째 아이템에서만 회사 타입 정보 저장
        if (!companyTypesMap.containsKey(item.companyId)) {
          List<CompanyType> types = [];
          
          // 1. company_types 필드가 있으면 우선 사용 (하위 호환성)
          if (item.companyTypes != null && item.companyTypes!.isNotEmpty) {
            types = item.companyTypes!.map((typeStr) {
              if (typeStr.toLowerCase().contains('partner')) return CompanyType.partner;
              return CompanyType.customer;
            }).toSet().toList(); // 중복 제거
          }
          // 2. company_types가 없으면 is_partner, is_customer 사용
          else {
            if (item.isCustomer) types.add(CompanyType.customer);
            if (item.isPartner) types.add(CompanyType.partner);
          }
          
          companyTypesMap[item.companyId] = types;
          companyIsPartnerMap[item.companyId] = item.isPartner;
          companyIsCustomerMap[item.companyId] = item.isCustomer;
        }
        
        if (item.branchId != null && item.branchName != null) {
          if (!companyBranchesMap.containsKey(item.companyId)) {
            companyBranchesMap[item.companyId] = [];
          }
          companyBranchesMap[item.companyId]!.add(
            Branch(
              id: item.branchId,
              companyId: item.companyId,
              name: item.branchName!,
              address: Address.fromFullAddress(''), // 주소 정보가 없으므로 빈 값
            ),
          );
        }
      }
      
      // Company 객체 생성
      final List<Company> companies = [];
      for (final entry in companyNamesMap.entries) {
        companies.add(
          Company(
            id: entry.key,
            name: entry.value,
            address: Address.fromFullAddress(''), // 주소 정보가 없으므로 빈 값
            companyTypes: companyTypesMap[entry.key] ?? [], // 빈 리스트 가능
            branches: companyBranchesMap[entry.key],  // null 허용
          ),
        );
      }
      
      return companies;
    } on ApiException catch (e) {
      debugPrint('[CompanyService] ApiException: ${e.message}');
      throw ServerFailure(message: e.message);
    } catch (e, stackTrace) {
      debugPrint('[CompanyService] Error loading companies with branches: $e');
      debugPrint('[CompanyService] Stack trace: $stackTrace');
      throw ServerFailure(message: 'Failed to fetch companies with branches: $e');
    }
  }

  // 변환 헬퍼 메서드들
  Company _convertListDtoToCompany(CompanyListDto dto) {
    List<CompanyType> companyTypes = [];
    
    // 1. company_types 필드가 있으면 우선 사용 (하위 호환성)
    if (dto.companyTypes != null && dto.companyTypes!.isNotEmpty) {
      companyTypes = dto.companyTypes!.map((typeStr) {
        if (typeStr.toLowerCase().contains('partner')) return CompanyType.partner;
        return CompanyType.customer;
      }).toSet().toList(); // 중복 제거
    } 
    // 2. company_types가 없으면 is_partner, is_customer 사용
    else {
      if (dto.isCustomer) companyTypes.add(CompanyType.customer);
      if (dto.isPartner) companyTypes.add(CompanyType.partner);
    }
    
    // 3. 둘 다 없으면 빈 리스트 유지 (기본값 제거)

    return Company(
      id: dto.id,
      name: dto.name,
      address: Address.fromFullAddress(dto.address ?? ''),
      contactName: dto.contactName,
      contactPosition: null, // CompanyListDto에는 position이 없음
      contactPhone: dto.contactPhone,
      contactEmail: dto.contactEmail,
      companyTypes: companyTypes,
      remark: null, // CompanyListDto에는 remark이 없음
      isActive: dto.isActive,
      isPartner: dto.isPartner,
      isCustomer: dto.isCustomer,
      parentCompanyId: dto.parentCompanyId,
      createdAt: dto.registeredAt, // CompanyListDto.registeredAt → createdAt
      updatedAt: null, // CompanyListDto에는 updatedAt이 없음
      branches: [], // branches는 빈 배열로 초기화
    );
  }

  Company _convertResponseToCompany(CompanyDto dto) {
    List<CompanyType> companyTypes = [];
    
    // CompanyDto에는 companyTypes 필드가 없으므로 is_partner, is_customer 사용
    if (dto.isCustomer) companyTypes.add(CompanyType.customer);
    if (dto.isPartner) companyTypes.add(CompanyType.partner);
    
    // 3. 둘 다 없으면 빈 리스트 유지

    return Company(
      id: dto.id,
      name: dto.name,
      address: dto.address != null ? Address.fromFullAddress(dto.address) : const Address(),
      contactName: dto.contactName,
      contactPosition: null, // CompanyDto에 contactPosition 필드 없음
      contactPhone: dto.contactPhone,
      contactEmail: dto.contactEmail,
      companyTypes: companyTypes,
      remark: dto.remark,
      isActive: dto.isActive,
      isPartner: dto.isPartner,
      isCustomer: dto.isCustomer,
      parentCompanyId: dto.parentCompanyId,
      createdAt: dto.registeredAt, // createdAt → registeredAt
      updatedAt: dto.updatedAt,
      branches: [], // branches는 빈 배열로 초기화
    );
  }

  // CompanyListDto를 CompanyItem으로 변환 (본사 목록용)
  CompanyItem _convertListDtoToCompanyItem(CompanyListDto dto) {
    final company = _convertListDtoToCompany(dto);
    return CompanyItem(company: company);
  }

  // DEPRECATED: Branch 변환 메서드들 (계층형 Company 구조로 대체)
  /*
  Branch _convertBranchDtoToBranch(BranchListDto dto) {
    return Branch(
      id: dto.id,
      companyId: dto.companyId,
      name: dto.branchName,
      address: Address.fromFullAddress(dto.address),
      contactName: dto.managerName,
      contactPhone: dto.phone,
    );
  }

  Branch _convertBranchResponseToBranch(BranchResponse dto) {
    return Branch(
      id: dto.id,
      companyId: dto.companyId,
      name: dto.branchName,
      address: Address.fromFullAddress(dto.address),
      contactName: dto.managerName,
      contactPhone: dto.phone,
      remark: dto.remark,
    );
  }
  */
  
  // 본사 목록 조회 (페이지네이션 포함) - 개수 확인용
  // 백엔드 /companies API에서 parentCompanyId == null 필터링
  Future<Either<Failure, PaginatedResponse<Company>>> getHeadquartersWithPagination() async {
    try {
      final response = await _remoteDataSource.getHeadquartersWithPagination();
      
      return Right(PaginatedResponse<Company>(
        items: response.items.map((dto) => _convertListDtoToCompany(dto)).toList(),
        page: response.page,
        size: response.size,
        totalElements: response.totalElements,
        totalPages: response.totalPages,
        first: response.first,
        last: response.last,
      ));
    } on ApiException catch (e) {
      debugPrint('[CompanyService] ApiException in getHeadquartersWithPagination: ${e.message}');
      return Left(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      debugPrint('[CompanyService] Error loading headquarters with pagination: $e');
      debugPrint('[CompanyService] Stack trace: $stackTrace');
      return Left(ServerFailure(message: 'Failed to load headquarters'));
    }
  }

  // 본사 목록 조회 (지점 추가 시 사용)
  Future<Either<Failure, List<CompanyItem>>> getHeadquarters() async {
    try {
      final response = await _remoteDataSource.getHeadquarters();
      final companyItems = response.map((dto) => _convertListDtoToCompanyItem(dto)).toList();
      return Right(companyItems);
    } on ApiException catch (e) {
      debugPrint('[CompanyService] ApiException in getHeadquarters: ${e.message}');
      return Left(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      debugPrint('[CompanyService] Error loading headquarters: $e');
      debugPrint('[CompanyService] Stack trace: $stackTrace');
      return Left(ServerFailure(message: 'Failed to fetch headquarters list: $e'));
    }
  }

  // 모든 본사 목록 조회 (지점 추가 드롭다운용 - 전체 목록 한번에 로드)
  Future<Either<Failure, List<CompanyItem>>> getAllHeadquarters() async {
    try {
      final response = await _remoteDataSource.getAllHeadquarters();
      final companyItems = response.map((dto) => _convertListDtoToCompanyItem(dto)).toList();
      return Right(companyItems);
    } on ApiException catch (e) {
      debugPrint('[CompanyService] ApiException in getAllHeadquarters: ${e.message}');
      return Left(ServerFailure(message: e.message));
    } catch (e, stackTrace) {
      debugPrint('[CompanyService] Error loading all headquarters: $e');
      debugPrint('[CompanyService] Stack trace: $stackTrace');
      return Left(ServerFailure(message: 'Failed to fetch all headquarters list: $e'));
    }
  }
}

// Company 모델에 copyWith 메서드가 없다면 extension으로 추가
extension CompanyExtension on Company {
  Company copyWith({
    int? id,
    String? name,
    Address? address,
    String? contactName,
    String? contactPosition,
    String? contactPhone,
    String? contactEmail,
    List<Branch>? branches,
    List<CompanyType>? companyTypes,
    String? remark,
  }) {
    return Company(
      id: id ?? this.id,
      name: name ?? this.name,
      address: address ?? this.address,
      contactName: contactName ?? this.contactName,
      contactPosition: contactPosition ?? this.contactPosition,
      contactPhone: contactPhone ?? this.contactPhone,
      contactEmail: contactEmail ?? this.contactEmail,
      branches: branches ?? this.branches,
      companyTypes: companyTypes ?? this.companyTypes,
      remark: remark ?? this.remark,
    );
  }
}