package com.erp.purchase.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.purchase.client.FinanceFeignClient;
import com.erp.purchase.client.WarehouseFeignClient;
import com.erp.purchase.dto.PurchaseOrderDTO;
import com.erp.purchase.entity.PurchaseOrder;
import com.erp.purchase.entity.Supplier;
import com.erp.purchase.enums.PurchaseOrderStatus;
import com.erp.purchase.exception.BusinessException;
import com.erp.purchase.mapper.PurchaseOrderMapper;
import com.erp.purchase.mapper.SupplierMapper;
import com.erp.purchase.service.PurchaseOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class PurchaseOrderServiceImpl implements PurchaseOrderService {

    private final PurchaseOrderMapper purchaseOrderMapper;
    private final SupplierMapper supplierMapper;
    private final WarehouseFeignClient warehouseClient;
    private final FinanceFeignClient financeClient;

    private static final AtomicLong ORDER_COUNTER = new AtomicLong(System.currentTimeMillis() % 100000);

    @Override
    public IPage<PurchaseOrder> listPage(PurchaseOrderDTO.QueryRequest query) {
        Page<PurchaseOrder> page = new Page<>(query.getPage(), query.getLimit());
        return purchaseOrderMapper.selectPageList(page, query.getOrderNo(), query.getSupplierId(),
                query.getStatus(), query.getStartDate(), query.getEndDate());
    }

    @Override
    public PurchaseOrder getById(Long id) {
        PurchaseOrder order = purchaseOrderMapper.selectById(id);
        if (order == null) throw new BusinessException("采购订单不存在");
        return order;
    }

    @Override
    public PurchaseOrder getByOrderNo(String orderNo) {
        PurchaseOrder order = purchaseOrderMapper.findByOrderNo(orderNo);
        if (order == null) throw new BusinessException("采购订单不存在: " + orderNo);
        return order;
    }

    @Override
    @Transactional
    public PurchaseOrder create(PurchaseOrderDTO.CreateRequest request, Long operatorId) {
        Supplier supplier = supplierMapper.selectById(request.getSupplierId());
        if (supplier == null) throw new BusinessException("供应商不存在");

        String orderNo = generateOrderNo();

        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal totalTax = BigDecimal.ZERO;
        List<PurchaseOrder.PurchaseOrderItem> items = new ArrayList<>();

        BigDecimal taxRate = request.getTaxRate() != null ? request.getTaxRate() : new BigDecimal("0.13");

        for (PurchaseOrderDTO.OrderItemRequest itemReq : request.getItems()) {
            BigDecimal amount = itemReq.getPrice().multiply(new BigDecimal(itemReq.getQuantity()));
            BigDecimal taxAmount = amount.multiply(taxRate).setScale(2, RoundingMode.HALF_UP);
            BigDecimal amountWithTax = amount.add(taxAmount);

            PurchaseOrder.PurchaseOrderItem item = PurchaseOrder.PurchaseOrderItem.builder()
                    .skuCode(itemReq.getSkuCode())
                    .skuName(itemReq.getSkuName())
                    .unit(itemReq.getUnit())
                    .price(itemReq.getPrice())
                    .taxPrice(itemReq.getPrice().multiply(taxRate.add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_UP))
                    .quantity(itemReq.getQuantity())
                    .deliveredQuantity(0)
                    .returnedQuantity(0)
                    .amount(amount)
                    .taxAmount(taxAmount)
                    .amountWithTax(amountWithTax)
                    .remark(itemReq.getRemark())
                    .build();
            items.add(item);

            totalAmount = totalAmount.add(amount);
            totalTax = totalTax.add(taxAmount);
        }

        PurchaseOrder order = PurchaseOrder.builder()
                .orderNo(orderNo)
                .supplierId(request.getSupplierId())
                .supplierName(supplier.getName())
                .warehouseId(request.getWarehouseId())
                .orderDate(request.getOrderDate() != null ? request.getOrderDate() : LocalDate.now())
                .expectedDate(request.getExpectedDate())
                .status(PurchaseOrderStatus.DRAFT.getCode())
                .totalAmount(totalAmount)
                .taxRate(taxRate)
                .taxAmount(totalTax)
                .totalWithTax(totalAmount.add(totalTax))
                .inboundAmount(BigDecimal.ZERO)
                .paidAmount(BigDecimal.ZERO)
                .currency(request.getCurrency() != null ? request.getCurrency() : "CNY")
                .paymentMethod(request.getPaymentMethod() != null ? request.getPaymentMethod() : supplier.getPaymentMethod())
                .contact(request.getContact())
                .phone(request.getPhone())
                .deliveryAddress(request.getDeliveryAddress())
                .remark(request.getRemark())
                .createBy(operatorId)
                .createTime(LocalDateTime.now())
                .updateBy(operatorId)
                .updateTime(LocalDateTime.now())
                .deleted(0)
                .items(items)
                .build();

        purchaseOrderMapper.insert(order);
        log.info("创建采购订单: orderNo={}, supplier={}, totalWithTax={}", orderNo, supplier.getName(), order.getTotalWithTax());
        return order;
    }

    @Override
    @Transactional
    public PurchaseOrder update(PurchaseOrderDTO.UpdateRequest request, Long operatorId) {
        PurchaseOrder order = purchaseOrderMapper.selectById(request.getId());
        if (order == null) throw new BusinessException("采购订单不存在");
        if (!PurchaseOrderStatus.DRAFT.getCode().equals(order.getStatus()) &&
            !PurchaseOrderStatus.PENDING.getCode().equals(order.getStatus())) {
            throw new BusinessException("只有草稿或待审批状态可以修改");
        }

        if (request.getSupplierId() != null) {
            Supplier supplier = supplierMapper.selectById(request.getSupplierId());
            if (supplier == null) throw new BusinessException("供应商不存在");
            order.setSupplierId(request.getSupplierId());
            order.setSupplierName(supplier.getName());
        }
        if (request.getWarehouseId() != null) order.setWarehouseId(request.getWarehouseId());
        if (request.getExpectedDate() != null) order.setExpectedDate(request.getExpectedDate());
        if (request.getTaxRate() != null) order.setTaxRate(request.getTaxRate());
        if (request.getPaymentMethod() != null) order.setPaymentMethod(request.getPaymentMethod());
        if (request.getContact() != null) order.setContact(request.getContact());
        if (request.getPhone() != null) order.setPhone(request.getPhone());
        if (request.getDeliveryAddress() != null) order.setDeliveryAddress(request.getDeliveryAddress());
        if (request.getRemark() != null) order.setRemark(request.getRemark());

        // 重新计算金额
        if (request.getItems() != null && !request.getItems().isEmpty()) {
            BigDecimal totalAmount = BigDecimal.ZERO;
            BigDecimal totalTax = BigDecimal.ZERO;
            List<PurchaseOrder.PurchaseOrderItem> items = new ArrayList<>();
            BigDecimal taxRate = order.getTaxRate();

            for (PurchaseOrderDTO.OrderItemRequest itemReq : request.getItems()) {
                BigDecimal amount = itemReq.getPrice().multiply(new BigDecimal(itemReq.getQuantity()));
                BigDecimal taxAmount = amount.multiply(taxRate).setScale(2, RoundingMode.HALF_UP);
                PurchaseOrder.PurchaseOrderItem item = PurchaseOrder.PurchaseOrderItem.builder()
                        .skuCode(itemReq.getSkuCode())
                        .skuName(itemReq.getSkuName())
                        .unit(itemReq.getUnit())
                        .price(itemReq.getPrice())
                        .quantity(itemReq.getQuantity())
                        .amount(amount)
                        .taxAmount(taxAmount)
                        .amountWithTax(amount.add(taxAmount))
                        .remark(itemReq.getRemark())
                        .build();
                items.add(item);
                totalAmount = totalAmount.add(amount);
                totalTax = totalTax.add(taxAmount);
            }
            order.setItems(items);
            order.setTotalAmount(totalAmount);
            order.setTaxAmount(totalTax);
            order.setTotalWithTax(totalAmount.add(totalTax));
        }

        order.setUpdateBy(operatorId);
        order.setUpdateTime(LocalDateTime.now());
        purchaseOrderMapper.updateById(order);
        log.info("更新采购订单: orderNo={}", order.getOrderNo());
        return order;
    }

    @Override
    @Transactional
    public void delete(Long id, Long operatorId) {
        PurchaseOrder order = purchaseOrderMapper.selectById(id);
        if (order == null) throw new BusinessException("采购订单不存在");
        if (!PurchaseOrderStatus.DRAFT.getCode().equals(order.getStatus())) {
            throw new BusinessException("只有草稿状态可以删除");
        }
        purchaseOrderMapper.deleteById(id);
        log.info("删除采购订单: orderNo={}", order.getOrderNo());
    }

    @Override
    @Transactional
    public PurchaseOrder approve(Long id, PurchaseOrderDTO.ApproveRequest request, Long operatorId) {
        PurchaseOrder order = purchaseOrderMapper.selectById(id);
        if (order == null) throw new BusinessException("采购订单不存在");
        if (!PurchaseOrderStatus.PENDING.getCode().equals(order.getStatus())) {
            throw new BusinessException("只有待审批状态可以审批");
        }

        order.setStatus(PurchaseOrderStatus.APPROVED.getCode());
        order.setApproverId(operatorId);
        order.setApproveTime(LocalDateTime.now());
        order.setApproveRemark(request.getApproveRemark());
        order.setUpdateBy(operatorId);
        order.setUpdateTime(LocalDateTime.now());
        purchaseOrderMapper.updateById(order);

        // 通知财务创建应付账款
        try {
            financeClient.createAccountsPayable(
                    FinanceFeignClient.AccountsPayableRequest.builder()
                            .purchaseOrderId(order.getId())
                            .purchaseOrderNo(order.getOrderNo())
                            .supplierId(order.getSupplierId())
                            .amount(order.getTotalWithTax())
                            .paymentMethod(order.getPaymentMethod())
                            .build());
        } catch (Exception e) {
            log.warn("通知财务创建应付账款失败: orderNo={}, error={}", order.getOrderNo(), e.getMessage());
        }

        log.info("审批采购订单: orderNo={}, approverId={}", order.getOrderNo(), operatorId);
        return order;
    }

    @Override
    @Transactional
    public void cancel(Long id, Long operatorId) {
        PurchaseOrder order = purchaseOrderMapper.selectById(id);
        if (order == null) throw new BusinessException("采购订单不存在");
        if (PurchaseOrderStatus.COMPLETED.getCode().equals(order.getStatus()) ||
            PurchaseOrderStatus.CANCELLED.getCode().equals(order.getStatus())) {
            throw new BusinessException("已完成或已取消的订单不能取消");
        }

        order.setStatus(PurchaseOrderStatus.CANCELLED.getCode());
        order.setUpdateBy(operatorId);
        order.setUpdateTime(LocalDateTime.now());
        purchaseOrderMapper.updateById(order);

        // 通知财务取消应付账款
        try {
            financeClient.cancelAccountsPayable(order.getOrderNo());
        } catch (Exception e) {
            log.warn("通知财务取消应付账款失败: orderNo={}, error={}", order.getOrderNo(), e.getMessage());
        }

        log.info("取消采购订单: orderNo={}", order.getOrderNo());
    }

    @Override
    @Transactional
    public void submit(Long id, Long operatorId) {
        PurchaseOrder order = purchaseOrderMapper.selectById(id);
        if (order == null) throw new BusinessException("采购订单不存在");
        if (!PurchaseOrderStatus.DRAFT.getCode().equals(order.getStatus())) {
            throw new BusinessException("只有草稿状态可以提交");
        }
        order.setStatus(PurchaseOrderStatus.PENDING.getCode());
        order.setUpdateBy(operatorId);
        order.setUpdateTime(LocalDateTime.now());
        purchaseOrderMapper.updateById(order);
        log.info("提交采购订单: orderNo={}", order.getOrderNo());
    }

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