package com.nanri.aiimage.modules.dedupe.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.nanri.aiimage.common.exception.BusinessException;
import com.nanri.aiimage.modules.dedupe.mapper.DedupeTotalDataMapper;
import com.nanri.aiimage.modules.dedupe.model.dto.DedupeTotalDataCreateRequest;
import com.nanri.aiimage.modules.dedupe.model.dto.DedupeTotalDataUpdateRequest;
import com.nanri.aiimage.modules.dedupe.model.entity.DedupeTotalDataEntity;
import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataImportVo;
import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataItemVo;
import com.nanri.aiimage.modules.dedupe.model.vo.DedupeTotalDataPageVo;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service
@RequiredArgsConstructor
public class DedupeTotalDataService {

    private final DedupeTotalDataMapper dedupeTotalDataMapper;

    public DedupeTotalDataPageVo page(long page, long pageSize, String keyword) {
        long safePage = Math.max(page, 1);
        long safePageSize = Math.min(Math.max(pageSize, 1), 100);
        String safeKeyword = keyword == null ? "" : keyword.trim();
        LambdaQueryWrapper<DedupeTotalDataEntity> query = new LambdaQueryWrapper<DedupeTotalDataEntity>()
                .like(!safeKeyword.isEmpty(), DedupeTotalDataEntity::getDataValue, safeKeyword)
                .orderByDesc(DedupeTotalDataEntity::getId);
        Long total = dedupeTotalDataMapper.selectCount(query);
        List<DedupeTotalDataItemVo> items = dedupeTotalDataMapper.selectList(query.last("LIMIT " + ((safePage - 1) * safePageSize) + ", " + safePageSize))
                .stream()
                .map(this::toItemVo)
                .toList();
        DedupeTotalDataPageVo vo = new DedupeTotalDataPageVo();
        vo.setItems(items);
        vo.setTotal(total);
        vo.setPage(safePage);
        vo.setPageSize(safePageSize);
        return vo;
    }

    @Transactional
    public DedupeTotalDataItemVo create(DedupeTotalDataCreateRequest request) {
        String dataValue = normalizeDataValue(request.getDataValue());
        ensureUnique(dataValue, null);
        DedupeTotalDataEntity entity = new DedupeTotalDataEntity();
        entity.setDataValue(dataValue);
        dedupeTotalDataMapper.insert(entity);
        return toItemVo(getById(entity.getId()));
    }

    @Transactional
    public DedupeTotalDataImportVo importFromExcel(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new BusinessException("请上传 xlsx 文件");
        }
        String filename = file.getOriginalFilename() == null ? "" : file.getOriginalFilename().toLowerCase();
        if (!(filename.endsWith(".xlsx") || filename.endsWith(".xls"))) {
            throw new BusinessException("仅支持 .xlsx 或 .xls 文件");
        }

        DataFormatter formatter = new DataFormatter();
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(inputStream)) {
            Sheet sheet = workbook.getSheetAt(0);
            Row headerRow = sheet.getRow(0);
            if (headerRow == null) {
                throw new BusinessException("Excel 表头为空");
            }

            Map<String, Integer> headerMap = new HashMap<>();
            for (int i = 0; i < headerRow.getLastCellNum(); i++) {
                Cell cell = headerRow.getCell(i);
                String value = normalizeExcelText(cell == null ? null : formatter.formatCellValue(cell));
                if (!value.isBlank() && !headerMap.containsKey(value)) {
                    headerMap.put(value, i);
                }
            }

            Integer asinIndex = headerMap.get("ASIN");
            if (asinIndex == null) {
                throw new BusinessException("缺少 ASIN 列");
            }

            Set<String> seenInFile = new HashSet<>();
            int totalRows = Math.max(sheet.getLastRowNum(), 0);
            int asinCount = 0;
            int insertedCount = 0;
            int skippedCount = 0;

            for (int rowNum = 1; rowNum <= sheet.getLastRowNum(); rowNum++) {
                Row row = sheet.getRow(rowNum);
                if (row == null) {
                    skippedCount++;
                    continue;
                }
                String asin = normalizeExcelText(formatter.formatCellValue(row.getCell(asinIndex)));
                if (asin.isBlank()) {
                    skippedCount++;
                    continue;
                }
                asinCount++;
                String dataValue = normalizeDataValue(asin);
                if (!seenInFile.add(dataValue)) {
                    skippedCount++;
                    continue;
                }
                if (existsDataValue(dataValue)) {
                    skippedCount++;
                    continue;
                }
                DedupeTotalDataEntity entity = new DedupeTotalDataEntity();
                entity.setDataValue(dataValue);
                dedupeTotalDataMapper.insert(entity);
                insertedCount++;
            }

            DedupeTotalDataImportVo vo = new DedupeTotalDataImportVo();
            vo.setTotalRows(totalRows);
            vo.setAsinCount(asinCount);
            vo.setInsertedCount(insertedCount);
            vo.setSkippedCount(skippedCount);
            return vo;
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            throw new BusinessException("导入 Excel 失败");
        }
    }

    @Transactional
    public DedupeTotalDataItemVo update(Long id, DedupeTotalDataUpdateRequest request) {
        DedupeTotalDataEntity entity = getById(id);
        String dataValue = normalizeDataValue(request.getDataValue());
        ensureUnique(dataValue, id);
        entity.setDataValue(dataValue);
        dedupeTotalDataMapper.updateById(entity);
        return toItemVo(getById(id));
    }

    @Transactional
    public void delete(Long id) {
        DedupeTotalDataEntity entity = getById(id);
        dedupeTotalDataMapper.deleteById(entity.getId());
    }

    private DedupeTotalDataEntity getById(Long id) {
        DedupeTotalDataEntity entity = dedupeTotalDataMapper.selectById(id);
        if (entity == null) {
            throw new BusinessException("数据不存在");
        }
        return entity;
    }

    private String normalizeDataValue(String value) {
        String dataValue = value == null ? "" : value.trim();
        if (dataValue.isEmpty()) {
            throw new BusinessException("数据不能为空");
        }
        return dataValue;
    }

    private void ensureUnique(String dataValue, Long excludeId) {
        LambdaQueryWrapper<DedupeTotalDataEntity> query = new LambdaQueryWrapper<DedupeTotalDataEntity>()
                .eq(DedupeTotalDataEntity::getDataValue, dataValue)
                .last("LIMIT 1");
        DedupeTotalDataEntity exists = dedupeTotalDataMapper.selectOne(query);
        if (exists != null && (excludeId == null || !exists.getId().equals(excludeId))) {
            throw new BusinessException("数据已存在");
        }
    }

    private boolean existsDataValue(String dataValue) {
        LambdaQueryWrapper<DedupeTotalDataEntity> query = new LambdaQueryWrapper<DedupeTotalDataEntity>()
                .eq(DedupeTotalDataEntity::getDataValue, dataValue)
                .last("LIMIT 1");
        return dedupeTotalDataMapper.selectOne(query) != null;
    }

    private String normalizeExcelText(String value) {
        if (value == null) {
            return "";
        }
        return value.replace("\ufeff", "")
                .replace("\u3000", " ")
                .replace("\r\n", " ")
                .replace("\r", " ")
                .replace("\n", " ")
                .replace("\t", " ")
                .trim()
                .replaceAll("\\s+", " ");
    }

    private DedupeTotalDataItemVo toItemVo(DedupeTotalDataEntity entity) {
        DedupeTotalDataItemVo vo = new DedupeTotalDataItemVo();
        vo.setId(entity.getId());
        vo.setDataValue(entity.getDataValue());
        vo.setCreatedAt(entity.getCreatedAt());
        return vo;
    }
}
