package com.social.media.infrastructure.persistence.repository;

import com.social.media.domain.company.aggregate.Company;
import com.social.media.domain.company.repository.CompanyRepository;
import com.social.media.domain.company.valueobject.CompanyId;
import com.social.media.domain.company.valueobject.CompanyPlan;
import com.social.media.domain.company.valueobject.CompanyStatus;
import com.social.media.domain.company.valueobject.Cnpj;
import com.social.media.domain.shared.valueobject.Email;
import com.social.media.infrastructure.persistence.entity.CompanyEntity;
import com.social.media.infrastructure.persistence.entity.CompanyPlanEntity;
import com.social.media.infrastructure.persistence.mapper.CompanyEntityMapper;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Implementation of CompanyRepository using JPA
 */
@Repository
public class CompanyRepositoryImpl implements CompanyRepository {
    
    private final CompanyEntityJpaRepository companyJpaRepository;
    private final CompanyEntityMapper companyEntityMapper;
    
    public CompanyRepositoryImpl(CompanyEntityJpaRepository companyJpaRepository, CompanyEntityMapper companyEntityMapper) {
        this.companyJpaRepository = companyJpaRepository;
        this.companyEntityMapper = companyEntityMapper;
    }
    
    @Override
    public Company save(Company company) {
        CompanyEntity entity = companyEntityMapper.toEntity(company);
        CompanyEntity savedEntity = companyJpaRepository.save(entity);
        return companyEntityMapper.toDomain(savedEntity);
    }
    
    @Override
    public Optional<Company> findById(CompanyId id) {
        return companyJpaRepository.findById(id.value())
            .map(companyEntityMapper::toDomain);
    }
    
    @Override
    public Optional<Company> findByEmail(Email email) {
        return companyJpaRepository.findByEmail(email.value())
            .map(companyEntityMapper::toDomain);
    }
    
    @Override
    public Optional<Company> findByCnpj(Cnpj cnpj) {
        return companyJpaRepository.findByCnpj(cnpj.value())
            .map(companyEntityMapper::toDomain);
    }
    
    @Override
    public boolean existsByEmail(Email email) {
        return companyJpaRepository.existsByEmail(email.value());
    }
    
    @Override
    public boolean existsByCnpj(Cnpj cnpj) {
        return companyJpaRepository.existsByCnpj(cnpj.value());
    }
    
    @Override
    public List<Company> findByStatus(CompanyStatus status) {
        return companyJpaRepository.findByStatus(mapToEntityStatus(status))
            .stream()
            .map(companyEntityMapper::toDomain)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<Company> findByPlan(CompanyPlan plan) {
        return companyJpaRepository.findAll()
            .stream()
            .filter(entity -> entity.getPlan() == mapToEntityPlan(plan))
            .map(companyEntityMapper::toDomain)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<Company> findActiveCompanies() {
        return companyJpaRepository.findByStatus(com.social.media.infrastructure.persistence.entity.CompanyStatusEntity.ACTIVE)
            .stream()
            .map(companyEntityMapper::toDomain)
            .collect(Collectors.toList());
    }
    
    @Override
    public List<Company> findByActivitySector(String activitySector) {
        return companyJpaRepository.findByActivitySector(activitySector)
            .stream()
            .map(companyEntityMapper::toDomain)
            .collect(Collectors.toList());
    }
    
    @Override
    public void delete(CompanyId id) {
        companyJpaRepository.deleteById(id.value());
    }
    
    @Override
    public long countCompanies() {
        return companyJpaRepository.count();
    }
    
    @Override
    public long countActiveCompanies() {
        return companyJpaRepository.countByStatus(com.social.media.infrastructure.persistence.entity.CompanyStatusEntity.ACTIVE);
    }
    
    @Override
    public long countByPlan(CompanyPlan plan) {
        return companyJpaRepository.findAll()
            .stream()
            .filter(entity -> entity.getPlan() == mapToEntityPlan(plan))
            .count();
    }
    
    // Helper methods for enum conversion
    private com.social.media.infrastructure.persistence.entity.CompanyStatusEntity mapToEntityStatus(CompanyStatus status) {
        return switch (status) {
            case ATIVO -> com.social.media.infrastructure.persistence.entity.CompanyStatusEntity.ACTIVE;
            case INATIVO -> com.social.media.infrastructure.persistence.entity.CompanyStatusEntity.INACTIVE;
            case SUSPENSO -> com.social.media.infrastructure.persistence.entity.CompanyStatusEntity.SUSPENDED;
            case CANCELADO -> com.social.media.infrastructure.persistence.entity.CompanyStatusEntity.PENDING;
        };
    }
    
    private CompanyPlanEntity mapToEntityPlan(CompanyPlan plan) {
        return switch (plan) {
            case BASICO -> CompanyPlanEntity.BASIC;
            case PREMIUM -> CompanyPlanEntity.PREMIUM;
            case ENTERPRISE -> CompanyPlanEntity.ENTERPRISE;
        };
    }
}
