package com.erp.finance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.finance.dto.*;
import com.erp.finance.entity.IncomeRecord;
import com.erp.finance.repository.IncomeRecordRepository;
import com.erp.finance.service.IncomeService;
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.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import com.erp.common.core.model.ApiResponse;

@Slf4j
@Service
@RequiredArgsConstructor
public class IncomeServiceImpl implements IncomeService {

    private final IncomeRecordRepository incomeRecordRepository;
    private static final AtomicLong INCOME_COUNTER = new AtomicLong(System.currentTimeMillis() % 100000);

    @Override
    @Transactional
    public IncomeRecord recordIncome(FinanceApiResponse.IncomeRecordRequest request) {
        log.info("[财务] 记录收款 orderNo={}, amount={}", request.getOrderNo(), request.getAmount());

        // 检查是否已存在（防止重复记录）
        IncomeRecord existing = incomeRecordRepository.findByOrderNo(request.getOrderNo());
        if (existing != null) {
            log.warn("[财务] 订单 {} 已存在收款记录, incomeNo={}", request.getOrderNo(), existing.getIncomeNo());
            return existing;
        }

        String incomeNo = generateIncomeNo();
        LocalDateTime paymentTime = LocalDateTime.now();
        if (StringUtils.hasText(request.getPaymentTime())) {
            try {
                paymentTime = LocalDateTime.parse(request.getPaymentTime(),
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            } catch (Exception e) {
                log.warn("解析支付时间失败: {}", request.getPaymentTime());
            }
        }

        IncomeRecord record = IncomeRecord.builder()
                .incomeNo(incomeNo)
                .orderNo(request.getOrderNo())
                .shortId(request.getShortId())
                .platform(request.getPlatform())
                .shopId(request.getShopId())
                .shopName(request.getShopName())
                .amount(request.getAmount())
                .discountAmount(request.getDiscountAmount() != null ? request.getDiscountAmount() : BigDecimal.ZERO)
                .actualAmount(request.getActualAmount() != null ? request.getActualAmount() : request.getAmount())
                .paymentMethod(request.getPaymentMethod())
                .paymentTime(paymentTime)
                .transactionId(request.getTransactionId())
                .accountNo(request.getAccountNo())
                .accountName(request.getAccountName())
                .status(IncomeRecord.STATUS_CONFIRMED)
                .source(IncomeRecord.SOURCE_ORDER)
                .remark(request.getRemark())
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .deleted(0)
                .build();

        incomeRecordRepository.insert(record);
        log.info("[财务] 收款记录创建成功 incomeNo={}, orderNo={}, amount={}",
                incomeNo, request.getOrderNo(), request.getAmount());
        return record;
    }

    @Override
    @Transactional
    public IncomeRecord confirmIncome(Long id, String operator) {
        IncomeRecord record = incomeRecordRepository.selectById(id);
        if (record == null) {
            throw new RuntimeException("收款记录不存在: " + id);
        }
        if (!IncomeRecord.STATUS_PENDING.equals(record.getStatus())) {
            throw new RuntimeException("只有待确认状态的收款记录可以确认");
        }
        record.setStatus(IncomeRecord.STATUS_CONFIRMED);
        record.setUpdateTime(LocalDateTime.now());
        incomeRecordRepository.updateById(record);
        log.info("[财务] 收款记录确认 incomeNo={}, operator={}", record.getIncomeNo(), operator);
        return record;
    }

    @Override
    @Transactional
    public void cancelIncome(Long id, String reason, String operator) {
        IncomeRecord record = incomeRecordRepository.selectById(id);
        if (record == null) {
            throw new RuntimeException("收款记录不存在: " + id);
        }
        record.setStatus(IncomeRecord.STATUS_CANCELLED);
        record.setRemark((record.getRemark() != null ? record.getRemark() + "; " : "") + "取消原因: " + reason);
        record.setUpdateTime(LocalDateTime.now());
        incomeRecordRepository.updateById(record);
        log.info("[财务] 收款记录取消 incomeNo={}, reason={}, operator={}", record.getIncomeNo(), reason, operator);
    }

    @Override
    public IPage<IncomeRecord> query(IncomeQueryRequest request) {
        Page<IncomeRecord> page = new Page<>(request.getPage(), request.getPageSize());
        LocalDateTime startDate = parseDate(request.getStartDate(), true);
        LocalDateTime endDate = parseDate(request.getEndDate(), false);
        return incomeRecordRepository.selectPageList(page,
                request.getOrderNo(), request.getShortId(),
                request.getPlatform(), request.getShopId(),
                request.getStatus(), startDate, endDate);
    }

    @Override
    public IncomeRecord getById(Long id) {
        return incomeRecordRepository.selectById(id);
    }

    @Override
    public IncomeRecord getByIncomeNo(String incomeNo) {
        return incomeRecordRepository.findByIncomeNo(incomeNo);
    }

    @Override
    public IncomeRecord getByOrderNo(String orderNo) {
        return incomeRecordRepository.findByOrderNo(orderNo);
    }

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

    @Override
    public FinanceReportResponse getIncomeStatistics(LocalDateTime startTime, LocalDateTime endTime) {
        BigDecimal totalIncome = sumConfirmedAmount(startTime, endTime);
        LambdaQueryWrapper<IncomeRecord> wrapper = new LambdaQueryWrapper<IncomeRecord>()
                .eq(IncomeRecord::getStatus, IncomeRecord.STATUS_CONFIRMED)
                .ge(IncomeRecord::getPaymentTime, startTime)
                .le(IncomeRecord::getPaymentTime, endTime);
        long count = incomeRecordRepository.selectCount(wrapper);

        return FinanceReportResponse.builder()
                .startDate(startTime.toLocalDate())
                .endDate(endTime.toLocalDate())
                .totalIncome(totalIncome)
                .incomeCount(count)
                .build();
    }

    private String generateIncomeNo() {
        String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        return "INC" + date + String.format("%05d", INCOME_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;
        }
    }
}
