package com.social.media.application.company.handler;

import com.social.media.application.company.command.CreateCompanyCommand;
import com.social.media.application.company.dto.CompanyResponseDto;
import com.social.media.domain.company.aggregate.Company;
import com.social.media.domain.company.repository.CompanyRepository;
import com.social.media.domain.company.valueobject.Address;
import com.social.media.domain.company.valueobject.Cnpj;
import com.social.media.domain.company.valueobject.CompanyPlan;
import com.social.media.domain.shared.valueobject.Email;
import com.social.media.domain.shared.valueobject.Phone;
import com.social.media.domain.shared.exception.BusinessRuleViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;

/**
 * Handler for CreateCompanyCommand
 */
@Service
@Transactional
public class CreateCompanyCommandHandler {
    
    private final CompanyRepository companyRepository;
    
    public CreateCompanyCommandHandler(CompanyRepository companyRepository) {
        this.companyRepository = companyRepository;
    }
    
    public CompanyResponseDto handle(CreateCompanyCommand command) {
        // Validate business rules
        validateEmailNotExists(command.email());
        validateCnpjNotExists(command.cnpj());
        
        // Create value objects
        Email email = new Email(command.email());
        Cnpj cnpj = new Cnpj(command.cnpj());
        Phone phone = command.phoneNumber() != null ? new Phone(command.phoneNumber()) : null;
        
        Address address = null;
        if (command.street() != null || command.city() != null) {
            address = new Address(
                command.street(),
                command.number(),
                command.complement(),
                command.neighborhood(),
                command.city(),
                command.state(),
                command.postalCode(),
                command.country()
            );
        }
        
        // Create company aggregate
        // Convert string plan to CompanyPlan enum
        CompanyPlan companyPlan;
        try {
            companyPlan = CompanyPlan.valueOf(command.plan().toUpperCase());
        } catch (IllegalArgumentException e) {
            throw new IllegalArgumentException("Invalid company plan: " + command.plan(), e);
        }
        
        Company company = Company.create(
            command.companyName(),
            email,
            cnpj,
            phone,
            command.website(),
            command.activitySector(),
            companyPlan,
            address
        );
        
        // Save company
        Company savedCompany = companyRepository.save(company);
        
        // Return DTO
        return mapToDto(savedCompany);
    }
    
    private void validateEmailNotExists(String email) {
        if (companyRepository.existsByEmail(new Email(email))) {
            throw new BusinessRuleViolationException("Email already exists: " + email);
        }
    }
    
    private void validateCnpjNotExists(String cnpj) {
        if (companyRepository.existsByCnpj(new Cnpj(cnpj))) {
            throw new BusinessRuleViolationException("CNPJ already exists: " + cnpj);
        }
    }
    
    private CompanyResponseDto mapToDto(Company company) {
        return CompanyResponseDto.builder()
            .id(company.getId().value().toString())
            .name(company.getName())
            .email(company.getEmail().value())
            .website(company.getWebsite())
            .description(company.getActivitySector())
            .phone(company.getPhone() != null ? company.getPhone().value() : null)
            .address(company.getAddress() != null ? company.getAddress().street() : null)
            .city(company.getAddress() != null ? company.getAddress().city() : null)
            .state(company.getAddress() != null ? company.getAddress().state() : null)
            .country(company.getAddress() != null ? company.getAddress().country() : null)
            .postalCode(company.getAddress() != null ? company.getAddress().zipCode() : null)
            .industry(company.getActivitySector())
            .employeeCount(1) // Default value
            .timezone("America/Sao_Paulo") // Default value
            .active(company.getStatus().name().equals("ACTIVE"))
            .logoUrl(company.getLogoUrl())
            .settings(Map.of("plan", company.getActivePlan().name()))
            .createdAt(company.getCreatedAt())
            .updatedAt(company.getUpdatedAt())
            .build();
    }
}

