package com.social.media.application.company.service;

import com.social.media.application.company.dto.CompanyDto;
import com.social.media.application.company.query.FindCompanyByIdQuery;
import com.social.media.application.company.query.FindCompanyByCnpjQuery;
import com.social.media.application.company.query.ListCompaniesQuery;
import com.social.media.application.ports.CompanyRepository;
import com.social.media.domain.company.Company;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;

/**
 * Service for handling Company queries.
 * Implements read operations following CQRS pattern.
 */
@Service
@Transactional(readOnly = true)
public class CompanyQueryService {
    
    private final CompanyRepository companyRepository;
    
    public CompanyQueryService(CompanyRepository companyRepository) {
        this.companyRepository = companyRepository;
    }
    
    /**
     * Find a company by its ID
     */
    public Optional<CompanyDto> handle(FindCompanyByIdQuery query) {
        return companyRepository.findById(query.companyId())
                .map(this::mapToDto);
    }
    
    /**
     * Find a company by its CNPJ
     */
    public Optional<CompanyDto> handle(FindCompanyByCnpjQuery query) {
        return companyRepository.findByCnpj(query.cnpj())
                .map(this::mapToDto);
    }
    
    /**
     * List companies with filtering and pagination
     */
    public List<CompanyDto> handle(ListCompaniesQuery query) {
        List<Company> companies = companyRepository.findWithFilters(
            query.status(),
            query.plan(),
            query.activitySector(),
            query.page(),
            query.size(),
            query.sortBy(),
            query.sortDirection()
        );
        
        return companies.stream()
                .map(this::mapToDto)
                .toList();
    }
    
    /**
     * Count total companies for pagination
     */
    public long countCompanies(ListCompaniesQuery query) {
        return companyRepository.countWithFilters(
            query.status(),
            query.plan(),
            query.activitySector()
        );
    }
    
    /**
     * Check if a CNPJ already exists
     */
    public boolean existsByCnpj(String cnpj) {
        return companyRepository.existsByCnpj(cnpj);
    }
    
    /**
     * Check if an email already exists
     */
    public boolean existsByEmail(String email) {
        return companyRepository.existsByEmail(email);
    }
    
    /**
     * Maps Company entity to CompanyDto
     */
    private CompanyDto mapToDto(Company company) {
        return new CompanyDto(
            company.getId(),
            company.getCnpj().getValue(),
            company.getName(),
            company.getName(), // tradeName not available, using name
            company.getEmail().getValue(),
            company.getPhone(),
            company.getWebsite(),
            company.getActivitySector(),
            company.getActivePlan(),
            company.getStatus(),
            company.getAddress() != null ? new CompanyDto.AddressDto(
                company.getAddress().getStreet(),
                company.getAddress().getNumber(),
                company.getAddress().getComplement(),
                company.getAddress().getNeighborhood(),
                company.getAddress().getCity(),
                company.getAddress().getState(),
                company.getAddress().getZipCode(),
                company.getAddress().getCountry()
            ) : null,
            // Convert Instant to LocalDateTime - this is a temporary fix
            company.getRegistrationDate() != null ? 
                java.time.LocalDateTime.ofInstant(company.getRegistrationDate(), java.time.ZoneId.systemDefault()) : null,
            company.getRegistrationDate() != null ? 
                java.time.LocalDateTime.ofInstant(company.getRegistrationDate(), java.time.ZoneId.systemDefault()) : null
        );
    }
}
