package com.ga.api.service.accounting;

import com.ga.api.controller.accounting.CloseJournalReq;
import com.ga.api.controller.accounting.GenerateEntriesReq;
import com.ga.common.exception.BizException;
import com.ga.common.exception.ErrorCode;
import com.ga.common.model.PageResponse;
import com.ga.core.mapper.accounting.ContractAccountingEntryMapper;
import com.ga.core.mapper.settle.PaymentMapper;
import com.ga.core.vo.accounting.ContractAccountingEntryResp;
import com.ga.core.vo.accounting.ContractAccountingEntrySearchParam;
import com.ga.core.vo.accounting.ContractAccountingEntryVO;
import com.ga.core.vo.settle.PaymentVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ContractAccountingService {

    private static final String DEBIT_ACCOUNT  = "8350"; // 지급수수료
    private static final String CREDIT_ACCOUNT = "2530"; // 미지급금

    private final ContractAccountingEntryMapper entryMapper;
    private final PaymentMapper paymentMapper;

    public PageResponse<ContractAccountingEntryResp> list(ContractAccountingEntrySearchParam param) {
        param.startPage();
        return PageResponse.of(entryMapper.selectList(param));
    }

    @Transactional
    public int generateFromPayments(GenerateEntriesReq req) {
        List<PaymentVO> payments = resolvePayments(req);
        if (payments.isEmpty()) throw new BizException(ErrorCode.NOT_FOUND);

        List<ContractAccountingEntryVO> entries = new ArrayList<>(payments.size());
        for (PaymentVO p : payments) {
            entries.add(buildEntry(p));
        }
        return entryMapper.insertBatch(entries);
    }

    @Transactional
    public int closeJournal(CloseJournalReq req) {
        if (req.getEntryIds() == null || req.getEntryIds().isEmpty()) {
            throw new BizException(ErrorCode.INVALID_PARAMETER);
        }
        return entryMapper.closeJournal(req.getEntryIds(), req.getJournalNo());
    }

    private List<PaymentVO> resolvePayments(GenerateEntriesReq req) {
        if (req.getPaymentIds() != null && !req.getPaymentIds().isEmpty()) {
            List<PaymentVO> result = new ArrayList<>();
            for (Long id : req.getPaymentIds()) {
                PaymentVO p = paymentMapper.selectById(id);
                if (p != null) result.add(p);
            }
            return result;
        }
        if (req.getSettleMonth() != null && !req.getSettleMonth().isBlank()) {
            return paymentMapper.selectBySettleMonth(req.getSettleMonth());
        }
        return List.of();
    }

    private ContractAccountingEntryVO buildEntry(PaymentVO p) {
        ContractAccountingEntryVO vo = new ContractAccountingEntryVO();
        vo.setPaymentId(p.getPaymentId());
        vo.setEntryDate(LocalDate.now());
        vo.setDebitAccount(DEBIT_ACCOUNT);
        vo.setCreditAccount(CREDIT_ACCOUNT);
        vo.setAmount(p.getNetAmount() != null ? p.getNetAmount() : p.getPayAmount());
        vo.setDescription("commission payment " + p.getPaymentId());
        return vo;
    }
}
