package br.gov.sigefp.common.service;

import br.gov.sigefp.common.api.dto.BankDTO;
import br.gov.sigefp.common.domain.Bank;
import br.gov.sigefp.common.repository.BankRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

/**
 * Serviço de aplicação para gestão de bancos.
 */
@Service
@RequiredArgsConstructor
@Transactional
public class BankService {

    private final BankRepository bankRepository;

    public BankDTO create(BankDTO dto) {
        // Validação: garantir unicidade de code
        if (bankRepository.existsByCode(dto.getCode())) {
            throw new IllegalArgumentException("Código de banco já existe: " + dto.getCode());
        }

        Bank bank = Bank.builder()
                .code(dto.getCode())
                .name(dto.getName())
                .swiftCode(dto.getSwiftCode())
                .build();

        Bank saved = bankRepository.save(bank);
        return toDTO(saved);
    }

    public BankDTO update(UUID id, BankDTO dto) {
        Bank bank = bankRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Banco não encontrado: " + id));

        if (dto.getCode() != null && !dto.getCode().equals(bank.getCode())) {
            // Validação: garantir unicidade de code
            if (bankRepository.existsByCode(dto.getCode())) {
                throw new IllegalArgumentException("Código de banco já existe: " + dto.getCode());
            }
            bank.setCode(dto.getCode());
        }

        if (dto.getName() != null) {
            bank.setName(dto.getName());
        }
        if (dto.getSwiftCode() != null) {
            bank.setSwiftCode(dto.getSwiftCode());
        }

        Bank saved = bankRepository.save(bank);
        return toDTO(saved);
    }

    @Transactional(readOnly = true)
    public BankDTO findById(UUID id) {
        Bank bank = bankRepository.findById(id)
                .orElseThrow(() -> new IllegalArgumentException("Banco não encontrado: " + id));
        return toDTO(bank);
    }

    @Transactional(readOnly = true)
    public BankDTO findByCode(String code) {
        Bank bank = bankRepository.findByCode(code)
                .orElseThrow(() -> new IllegalArgumentException("Banco não encontrado com código: " + code));
        return toDTO(bank);
    }

    @Transactional(readOnly = true)
    public Page<BankDTO> findAll(Pageable pageable) {
        return bankRepository.findAll(pageable).map(this::toDTO);
    }

    private BankDTO toDTO(Bank bank) {
        return BankDTO.builder()
                .id(bank.getId())
                .code(bank.getCode())
                .name(bank.getName())
                .swiftCode(bank.getSwiftCode())
                .build();
    }
}

