package com.ruoyi.web.modules.industryservice.support;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
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.apache.poi.ss.usermodel.WorkbookFactory;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.modules.industryservice.domain.BizLivestockOwnershipHousehold;

/**
 * 有无畜户 Excel 解析（对齐 {@code livestock_ownership_household_import_template.xlsx}）。
 * <p>
 * 表头为两行：主表头含「乡镇/村居/有畜户/无畜户」，次表头为户数/人数/有劳力/牲畜数等；
 * 数据从主表头行 +2 开始。
 * </p>
 */
public final class LivestockOwnershipHouseholdExcelParser
{
    public static final String TEMPLATE_CLASSPATH = "templates/livestock_ownership_household_import_template.xlsx";

    static final int COL_SEQ = 0;

    static final int COL_TOWN = 1;

    static final int COL_VILLAGE = 2;

    static final int COL_WITH_HOUSEHOLD = 3;

    static final int COL_WITH_POPULATION = 4;

    static final int COL_WITH_LABOR = 5;

    static final int COL_WITH_ANIMAL = 6;

    static final int COL_WITHOUT_HOUSEHOLD = 7;

    static final int COL_WITHOUT_POPULATION = 8;

    static final int COL_WITHOUT_LABOR = 9;

    static final int COL_LAST = COL_WITHOUT_LABOR;

    private static final DataFormatter FORMATTER = new DataFormatter();

    private LivestockOwnershipHouseholdExcelParser()
    {
    }

    public static List<ParsedRow> parse(InputStream inputStream)
    {
        try (Workbook workbook = WorkbookFactory.create(inputStream))
        {
            Sheet sheet = resolveSheet(workbook);
            int headerRowIndex = detectHeaderRow(sheet);
            if (headerRowIndex < 0)
            {
                throw new ServiceException("未识别到表头行（乡镇/村居/有畜户）");
            }
            // 双行表头：主表头下一行为子表头，再下一行起为数据
            int dataStartRow = headerRowIndex + 2;
            List<ParsedRow> rows = new ArrayList<>();
            for (int i = dataStartRow; i <= sheet.getLastRowNum(); i++)
            {
                Row row = sheet.getRow(i);
                if (row == null)
                {
                    continue;
                }
                String townName = cellString(row, COL_TOWN);
                String seqText = cellString(row, COL_SEQ);
                if (StringUtils.isNotEmpty(seqText) && seqText.contains("合计"))
                {
                    break;
                }
                if (StringUtils.isNotEmpty(townName) && townName.contains("合计"))
                {
                    break;
                }
                if (StringUtils.isEmpty(townName))
                {
                    continue;
                }
                ParsedRow parsed = new ParsedRow();
                parsed.setExcelRowNum(i + 1);
                parsed.setTownName(townName.trim());
                parsed.setVillageName(cellString(row, COL_VILLAGE));
                parsed.setWithLivestockHouseholdCount(cellInteger(row, COL_WITH_HOUSEHOLD));
                parsed.setWithLivestockPopulationCount(cellInteger(row, COL_WITH_POPULATION));
                parsed.setWithLivestockLaborCount(cellInteger(row, COL_WITH_LABOR));
                parsed.setWithLivestockAnimalCount(cellInteger(row, COL_WITH_ANIMAL));
                parsed.setWithoutLivestockHouseholdCount(cellInteger(row, COL_WITHOUT_HOUSEHOLD));
                parsed.setWithoutLivestockPopulationCount(cellInteger(row, COL_WITHOUT_POPULATION));
                parsed.setWithoutLivestockLaborCount(cellInteger(row, COL_WITHOUT_LABOR));
                rows.add(parsed);
            }
            return rows;
        }
        catch (ServiceException ex)
        {
            throw ex;
        }
        catch (Exception ex)
        {
            throw new ServiceException("Excel 解析失败：" + ex.getMessage());
        }
    }

    static Sheet resolveSheet(Workbook workbook)
    {
        for (int i = 0; i < workbook.getNumberOfSheets(); i++)
        {
            Sheet sheet = workbook.getSheetAt(i);
            String name = sheet.getSheetName();
            if (name != null && (name.contains("有无畜户") || name.contains("畜户")))
            {
                return sheet;
            }
        }
        return workbook.getSheetAt(0);
    }

    /**
     * 定位主表头行（含乡镇、村居/村、有畜户）。
     */
    static int detectHeaderRow(Sheet sheet)
    {
        int last = Math.min(sheet.getLastRowNum(), 30);
        for (int i = 0; i <= last; i++)
        {
            Row row = sheet.getRow(i);
            if (row == null)
            {
                continue;
            }
            String townHeader = cellString(row, COL_TOWN);
            String villageHeader = cellString(row, COL_VILLAGE);
            String withHeader = cellString(row, COL_WITH_HOUSEHOLD);
            if (StringUtils.isNotEmpty(townHeader) && townHeader.contains("乡镇")
                    && StringUtils.isNotEmpty(villageHeader)
                    && (villageHeader.contains("村") || villageHeader.contains("居"))
                    && StringUtils.isNotEmpty(withHeader) && withHeader.contains("有畜户"))
            {
                return i;
            }
        }
        return -1;
    }

    static String cellString(Row row, int colIndex)
    {
        Cell cell = row.getCell(colIndex);
        if (cell == null)
        {
            return null;
        }
        String text = FORMATTER.formatCellValue(cell);
        return StringUtils.isEmpty(text) ? null : text.trim();
    }

    static Integer cellInteger(Row row, int colIndex)
    {
        String text = cellString(row, colIndex);
        if (StringUtils.isEmpty(text))
        {
            return null;
        }
        try
        {
            return (int) Math.round(Double.parseDouble(text.replace(",", "")));
        }
        catch (NumberFormatException ex)
        {
            throw new ServiceException("第" + (row.getRowNum() + 1) + "行数字格式错误");
        }
    }

    public static BizLivestockOwnershipHousehold toEntity(ParsedRow parsed, Integer statYear, Integer statMonth,
            Long townDeptId, String townName, Long villageDeptId, String villageName)
    {
        BizLivestockOwnershipHousehold row = new BizLivestockOwnershipHousehold();
        row.setStatYear(statYear);
        row.setStatMonth(statMonth);
        row.setTownDeptId(townDeptId);
        row.setTownName(townName);
        row.setVillageDeptId(villageDeptId);
        row.setVillageName(villageName);
        row.setWithLivestockHouseholdCount(parsed.getWithLivestockHouseholdCount());
        row.setWithLivestockPopulationCount(parsed.getWithLivestockPopulationCount());
        row.setWithLivestockLaborCount(parsed.getWithLivestockLaborCount());
        row.setWithLivestockAnimalCount(parsed.getWithLivestockAnimalCount());
        row.setWithoutLivestockHouseholdCount(parsed.getWithoutLivestockHouseholdCount());
        row.setWithoutLivestockPopulationCount(parsed.getWithoutLivestockPopulationCount());
        row.setWithoutLivestockLaborCount(parsed.getWithoutLivestockLaborCount());
        return row;
    }

    public static class ParsedRow
    {
        private int excelRowNum;

        private String townName;

        private String villageName;

        private Integer withLivestockHouseholdCount;

        private Integer withLivestockPopulationCount;

        private Integer withLivestockLaborCount;

        private Integer withLivestockAnimalCount;

        private Integer withoutLivestockHouseholdCount;

        private Integer withoutLivestockPopulationCount;

        private Integer withoutLivestockLaborCount;

        public int getExcelRowNum()
        {
            return excelRowNum;
        }

        public void setExcelRowNum(int excelRowNum)
        {
            this.excelRowNum = excelRowNum;
        }

        public String getTownName()
        {
            return townName;
        }

        public void setTownName(String townName)
        {
            this.townName = townName;
        }

        public String getVillageName()
        {
            return villageName;
        }

        public void setVillageName(String villageName)
        {
            this.villageName = villageName;
        }

        public Integer getWithLivestockHouseholdCount()
        {
            return withLivestockHouseholdCount;
        }

        public void setWithLivestockHouseholdCount(Integer withLivestockHouseholdCount)
        {
            this.withLivestockHouseholdCount = withLivestockHouseholdCount;
        }

        public Integer getWithLivestockPopulationCount()
        {
            return withLivestockPopulationCount;
        }

        public void setWithLivestockPopulationCount(Integer withLivestockPopulationCount)
        {
            this.withLivestockPopulationCount = withLivestockPopulationCount;
        }

        public Integer getWithLivestockLaborCount()
        {
            return withLivestockLaborCount;
        }

        public void setWithLivestockLaborCount(Integer withLivestockLaborCount)
        {
            this.withLivestockLaborCount = withLivestockLaborCount;
        }

        public Integer getWithLivestockAnimalCount()
        {
            return withLivestockAnimalCount;
        }

        public void setWithLivestockAnimalCount(Integer withLivestockAnimalCount)
        {
            this.withLivestockAnimalCount = withLivestockAnimalCount;
        }

        public Integer getWithoutLivestockHouseholdCount()
        {
            return withoutLivestockHouseholdCount;
        }

        public void setWithoutLivestockHouseholdCount(Integer withoutLivestockHouseholdCount)
        {
            this.withoutLivestockHouseholdCount = withoutLivestockHouseholdCount;
        }

        public Integer getWithoutLivestockPopulationCount()
        {
            return withoutLivestockPopulationCount;
        }

        public void setWithoutLivestockPopulationCount(Integer withoutLivestockPopulationCount)
        {
            this.withoutLivestockPopulationCount = withoutLivestockPopulationCount;
        }

        public Integer getWithoutLivestockLaborCount()
        {
            return withoutLivestockLaborCount;
        }

        public void setWithoutLivestockLaborCount(Integer withoutLivestockLaborCount)
        {
            this.withoutLivestockLaborCount = withoutLivestockLaborCount;
        }
    }
}
