package com.erp.finance.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.finance.dto.PaymentQueryRequest;
import com.erp.finance.entity.PaymentRecord;
import com.erp.finance.repository.PaymentRecordRepository;
import com.erp.finance.service.PaymentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
@Service
@RequiredArgsConstructor
public class PaymentServiceImpl implements PaymentService {

    private final PaymentRecordRepository paymentRecordRepository;
    private static final AtomicLong PAYMENT_COUNTER = new AtomicLong(System.currentTimeMillis() % 100000);

    @Override
    @Transactional
    public PaymentRecord createPaymentRecord(PaymentCreateRequest request) {
        log.info("[财务] 创建付款记录 apNo={}, amount={}, purpose={}",
                request.getApNo(), request.getAmount(), request.getPurpose());

        String paymentNo = generatePaymentNo();
        PaymentRecord record = PaymentRecord.builder()
                .paymentNo(paymentNo)
                .apNo(request.getApNo())
                .apId(request.getApId())
                .purchaseOrderNo(request.getPurchaseOrderNo())
                .supplierId(request.getSupplierId())
                .supplierName(request.getSupplierName())
                .amount(request.getAmount())
                .paymentMethod(request.getPaymentMethod())
                .fromAccount(request.getFromAccount())
                .toAccount(request.getToAccount())
                .paymentTime(LocalDateTime.now())
                .bankFlowNo(request.getBankFlowNo())
                .status(PaymentRecord.STATUS_PENDING)
                .purpose(request.getPurpose())
                .relatedId(request.getRelatedId())
                .relatedType(request.getRelatedType())
                .operator(request.getOperator())
                .remark(request.getRemark())
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .deleted(0)
                .build();

        paymentRecordRepository.insert(record);
        log.info("[财务] 付款记录创建成功 paymentNo={}", paymentNo);
        return record;
    }

    @Override
    @Transactional
    public PaymentRecord confirmPayment(Long id, String operator) {
        PaymentRecord record = paymentRecordRepository.selectById(id);
        if (record == null) {
            throw new RuntimeException("付款记录不存在: " + id);
        }
        if (!PaymentRecord.STATUS_PENDING.equals(record.getStatus())) {
            throw new RuntimeException("只有待付款的记录可以确认");
        }
        record.setStatus(PaymentRecord.STATUS_COMPLETED);
        record.setPaymentTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        paymentRecordRepository.updateById(record);
        log.info("[财务] 付款确认 paymentNo={}, operator={}", record.getPaymentNo(), operator);
        return record;
    }

    @Override
    @Transactional
    public void cancelPayment(Long id, String reason, String operator) {
        PaymentRecord record = paymentRecordRepository.selectById(id);
        if (record == null) {
            throw new RuntimeException("付款记录不存在: " + id);
        }
        if (!PaymentRecord.STATUS_PENDING.equals(record.getStatus())) {
            throw new RuntimeException("只有待付款的记录可以取消");
        }
        record.setStatus(PaymentRecord.STATUS_FAILED);
        record.setRemark((record.getRemark() != null ? record.getRemark() + "; " : "") + "取消原因: " + reason);
        record.setUpdateTime(LocalDateTime.now());
        paymentRecordRepository.updateById(record);
        log.info("[财务] 付款取消 paymentNo={}, reason={}, operator={}", record.getPaymentNo(), reason, operator);
    }

    @Override
    public IPage<PaymentRecord> query(PaymentQueryRequest request) {
        Page<PaymentRecord> page = new Page<>(request.getPage(), request.getPageSize());
        LocalDateTime startDate = parseDate(request.getStartDate(), true);
        LocalDateTime endDate = parseDate(request.getEndDate(), false);
        return paymentRecordRepository.selectPageList(page,
                request.getApNo(), request.getPurchaseOrderNo(),
                request.getSupplierId(), request.getStatus(),
                request.getPurpose(), startDate, endDate);
    }

    @Override
    public PaymentRecord getById(Long id) {
        return paymentRecordRepository.selectById(id);
    }

    @Override
    public PaymentRecord getByPaymentNo(String paymentNo) {
        return paymentRecordRepository.findByPaymentNo(paymentNo);
    }

    @Override
    public BigDecimal sumCompletedPaymentAmount(LocalDateTime startTime, LocalDateTime endTime) {
        BigDecimal amount = paymentRecordRepository.sumCompletedPaymentAmount(startTime, endTime);
        return amount != null ? amount : BigDecimal.ZERO;
    }

    private String generatePaymentNo() {
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        return "PAY" + date + String.format("%05d", PAYMENT_COUNTER.incrementAndGet());
    }

    private LocalDateTime parseDate(String dateStr, boolean startOfDay) {
        if (!StringUtils.hasText(dateStr)) return null;
        try {
            LocalDate date = LocalDate.parse(dateStr);
            return startOfDay ? date.atStartOfDay() : date.atTime(23, 59, 59);
        } catch (Exception e) {
            return null;
        }
    }
}
