package com.ruoyi.pay.util;

import cn.hutool.core.lang.Dict;
import com.ruoyi.common.core.service.DictService;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.pay.domain.PayAttendance;
import com.ruoyi.pay.domain.bo.PayAttendanceBo;
import com.ruoyi.pay.service.IPayAttendanceService;
import org.springframework.stereotype.Component;

import cn.hutool.core.date.DateTime;

import org.apache.poi.ss.usermodel.Row;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;

import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class AttendanceExcelUtil {

    private final IPayAttendanceService iPayAttendanceService;
    private final DictService dictService;

    public AttendanceExcelUtil() {
        this.iPayAttendanceService = SpringUtils.getBean(IPayAttendanceService.class);
        this.dictService = SpringUtils.getBean(DictService.class);
    }

    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);

    public static final String FORMULA_REGEX_STR = "=|-|\\+|@";

    public static final String[] FORMULA_STR = { "=", "-", "+", "@" };

    /**
     * Excel sheet最大行数，默认65536
     */
    public static final int sheetSize = 65536;

    /**
     * 工作表名称
     */
    private String sheetName;

    /**
     * 导出类型（EXPORT:导出数据；IMPORT：导入模板）
     */
    //private Excel.Type type;

    /**
     * 工作薄对象
     */
    private Workbook wb;

    /**
     * 工作表对象
     */
    private Sheet sheet;

    /**
     * 样式列表
     */
    private Map<String, CellStyle> styles;

    /**
     * 导入导出数据列表
     */
    private List<PayAttendance> list;

    /**
     * 注解列表
     */
    private List<Object[]> fields;

    /**
     * 当前行号
     */
    private int rownum;

    /**
     * 标题
     */
    private String title;

    /**
     * 最大高度
     */
    private short maxHeight;

    /**
     * 统计列表
     */
    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();

    /**
     * 数字格式
     */
    private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");

    /**
     * 实体对象
     */
    public Class<PayAttendance> clazz;

    /**
     * 对excel表单指定表格索引名转换成list
     *
     * @param sheetName 表格索引名
     * @param titleNum 标题占用行数
     * @param is 输入流
     * @return 转换后集合
     */
    public  List<PayAttendanceBo> importKaoQinExcel(String sheetName, InputStream is, int titleNum, String date,String kaoqinType,Long tenantId) throws Exception {
        List<PayAttendanceBo> attendances = new ArrayList<>();
        //this.type = Excel.Type.IMPORT;
        this.wb = WorkbookFactory.create(is);

        // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第1个sheet
        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(2);
        if (sheet == null) {
            throw new IOException("文件sheet不存在");
        }
       /* boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
      Map<String, PictureData> pictures;
        if (isXSSFWorkbook) {
            pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
        } else {
            pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
        }*/

        // 获取最后一个非空行的行下标，比如总行数为n，则返回的为n-1
        int rows = sheet.getLastRowNum();
        //把日期存放到list中
        List<String> days = new ArrayList<>();
        if (rows > 0) {
            // 定义一个map用于存放excel列的序号和field.
            Map<String, Integer> cellMap = new HashMap<String, Integer>();
            // 获取表头
           /* Row heard = sheet.getRow(titleNum);
            String[] yearAndMonth =date.split("-");
            for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++) {
                Cell cell = heard.getCell(i);
                if (StringUtils.isNotNull(cell)) {
                    String value = this.getCellValue(heard, i).toString();
                    if(value!=null&&!value.trim().equals("")){
                        if(i<9){
                            value=0+value;
                        }
                      days.add(value);
                    }
                }
            }*/
            int dayNumOfMonth = getDaysOfMonth(date);
            for (Integer i = 1; i <= dayNumOfMonth; i++) {
                if(i<=9){
                    days.add("0"+i);
                }else {
                    days.add(i.toString());
                }
            }
            //每2行是一条员工数据,除第titlenum行外，一次循环2行
            for (int i = titleNum + 1; i <= rows; i += 2) {
                // 从第2行开始取数据,默认第一行是表头.
                Row row1 = sheet.getRow(i);
                Row row2 = sheet.getRow(i + 1);
                // 判断当前行是否是空行
                if (isRowEmpty(row1)) {
                    continue;
                }
                String wid = this.getCellValue(row1, 2).toString();//考勤机工号
                String wname = this.getCellValue(row1, 10).toString();
                //根据员工name查询员工id、部门id、部门名称
                PayAttendance  info  =  iPayAttendanceService.selectEmpInfoByName(wname);
                if(info==null){
                    throw new IOException("请先在员工表中添加员工："+wname+" 或者考勤机选择错误");
                }
                for (int j = 0; j < row2.getPhysicalNumberOfCells(); j++) {
                    if((j+1)>days.size()){
                        break;
                    }
                    PayAttendanceBo attendance = new PayAttendanceBo();
                    //attendance.setTenantId(LoginHelper.getTenantId());
                    attendance.setTenantId(tenantId);
                    attendance.setKaoqinYearMonth(date);
                    attendance.setEmpName(wname);
                    attendance.setKaoqinjiNum(kaoqinType);
                    attendance.setEmployeeId(info.getEmployeeId());
                    attendance.setDeptId(info.getDeptId());
                    attendance.setDeptName(info.getDeptName());
                    //得到年月日

                    String strday = date+"-"+days.get(j);
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    Date day = sdf.parse(strday);
                    attendance.setKaoqinDate(day);

                    Cell cell = row2.getCell(j);
                    if (!(null==cell)) {
                        String value = this.getCellValue(row2, j).toString();
                        // System.out.println("*************************************:" + value);
                        if (value != null && !value.trim().equals("")) {  //判断非空或者非空串单元格
                            String[] times = value.split("\n");
                            /*  Date standard = new DateTime(strday + " 13:00:00");//以13点为分界线，改为去字典配置分界时间，去字典中去值*/
                            Date standard = new DateTime(strday + " " +dictService.getDictValue("time_divid","noon_time"));//以字典值为分界线
                            List<Date> ams = new ArrayList<>();//上午时间段内
                            List<Date> pms = new ArrayList<>();//下午时间短内
                            SimpleDateFormat punchTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            for (String t : times) {
                                Date time = punchTime.parse(strday + " " + t + ":00");
                                if (time.before(standard)) {
                                    ams.add(time);
                                } else {
                                    pms.add(time);
                                }
                            }
                            //判断上下午时间段有几个值，对应存储
                            switch (ams.size()) {
                                case 0:
                                    break;
                                case 1:
                                    if(ams.get(0).before(punchTime.parse(strday+" 10:30:00"))){  //上午只打了一次卡 过了上午10点半算下班卡
                                        attendance.setAmStartTime(ams.get(0));
                                    }else{
                                        attendance.setAmEndTime(ams.get(0));
                                    }
                                    break;
                                default:
                                    List<Date> amtimes = getDates(ams);
                                    attendance.setAmStartTime(amtimes.get(0));
                                    attendance.setAmEndTime(amtimes.get(1));
                                    break;
                            }
                            switch (pms.size()) {
                                case 0:
                                    break;
                                case 1:
                                    if(pms.get(0).before(punchTime.parse(strday+" 16:30:00"))){  //下午只打了一次卡 过了下午四点半算下班卡
                                        attendance.setPmStartTime(pms.get(0));
                                    }else{
                                        attendance.setPmEndTime(pms.get(0));
                                    }
                                    break;
                                default:
                                    List<Date> pmtimes = getDates(pms);
                                    attendance.setPmStartTime(pmtimes.get(0));
                                    attendance.setPmEndTime(pmtimes.get(1));
                                    break;
                            }
                        }
                    }
                    attendances.add(attendance);
                }
            }
        }
        return attendances;
    }
    /**
     * 获取单元格值
     *
     * @param row 获取的行
     * @param column 获取单元格列号
     * @return 单元格值
     */
    public Object getCellValue(Row row, int column)
    {
        if (row == null)
        {
            return row;
        }
        Object val = "";
        try
        {
            Cell cell = row.getCell(column);
            if (!(null==cell))
            {
                if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
                {
                    val = cell.getNumericCellValue();
                    if (DateUtil.isCellDateFormatted(cell))
                    {
                        val = DateUtil.getJavaDate((Double) val); // POI Excel 日期格式转换
                    }
                    else
                    {
                        if ((Double) val % 1 != 0)
                        {
                            val = new BigDecimal(val.toString());
                        }
                        else
                        {
                            val = new DecimalFormat("0").format(val);
                        }
                    }
                }
                else if (cell.getCellType() == CellType.STRING)
                {
                    val = cell.getStringCellValue();
                }
                else if (cell.getCellType() == CellType.BOOLEAN)
                {
                    val = cell.getBooleanCellValue();
                }
                else if (cell.getCellType() == CellType.ERROR)
                {
                    val = cell.getErrorCellValue();
                }

            }
        }
        catch (Exception e)
        {
            return val;
        }
        return val;
    }

    /**
     * 判断是否是空行
     *
     * @param row 判断的行
     * @return
     */
    private boolean isRowEmpty(Row row)
    {
        if (row == null)
        {
            return true;
        }
        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
        {
            Cell cell = row.getCell(i);
            if (cell != null && cell.getCellType() != CellType.BLANK)
            {
                return false;
            }
        }
        return true;
    }
    /**
     * 返回日期中的最大值  最小值
     */
    private List<Date>  getDates(List<Date> dates){
        List<Date>  times = new ArrayList<>();
        Date max = dates.get(0);
        Date min = dates.get(0);
        for(Date time:dates){
            if(time.before(max)){
                min = time;
            }else{
                max = time;
            }
        }
        times.add(min);
        times.add(max);
        return times;
    }

    public List<PayAttendanceBo> importKaoQinExcel2(String empty, InputStream inputStream, int titleNum, String date,String kaoqinType,Long tenantId) throws Exception{
        List<PayAttendanceBo> attendances = new ArrayList<>();
       // this.type = Excel.Type.IMPORT;
        this.wb = WorkbookFactory.create(inputStream);

        // 如果指定sheet名,则取指定sheet中的内容 否则默认指向第3个sheet
        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(2);
        if (sheet == null) {
            throw new IOException("文件sheet不存在");
        }
        boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
        /*Map<String, PictureData> pictures;
        if (isXSSFWorkbook) {
            pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
        } else {
            pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
        }*/
        // 获取最后一个非空行的行下标，比如总行数为n，则返回的为n-1
        int rows = sheet.getLastRowNum();
        //把日期存放到list中
        List<String> days = new ArrayList<>();
        if (rows > 0) {
            // 定义一个map用于存放excel列的序号和field.
            Map<String, Integer> cellMap = new HashMap<String, Integer>();
            // 获取表头
            /*Row heard = sheet.getRow(titleNum);

            for (int i = 3; i < heard.getPhysicalNumberOfCells(); i++) {
                Cell cell = heard.getCell(i);
                if (StringUtils.isNotNull(cell)) {
                    String value = this.getCellValue(heard, i).toString();
                    if(value!=null&&!value.trim().equals("")){
                        if(i<9){
                            value=0+value;
                        }
                        days.add(value);
                    }
                }
            }*/
            int dayNumOfMonth = getDaysOfMonth(date);
            for (Integer i = 1; i <= dayNumOfMonth; i++) {
                if(i<=9){
                    days.add("0"+i);
                }else {
                    days.add(i.toString());
                }
            }


            //每1行是一条员工数据,除第titlenum+2行外，一次循环1行
            for (int i = titleNum + 2; i <= rows; i++) {
                // 从第2行开始取数据,默认第一行是表头.
                Row row1 = sheet.getRow(i);
                // 判断当前行是否是空行
                if (isRowEmpty(row1)) {
                    continue;
                }
                String wid = this.getCellValue(row1, 0).toString();//考勤机工号
                String wname = this.getCellValue(row1, 1).toString();//姓名
                //根据员工name查询员工id、部门id、部门名称
                PayAttendance info  =  iPayAttendanceService.selectEmpInfoByName(wname);
                if(info==null){
                    throw new IOException("请先在员工表中添加员工："+wname+" 或者考勤机选择错误");
                }
                for (int j = 3; j < row1.getPhysicalNumberOfCells(); j++) {
                    if((j-2)>days.size()){
                        break;
                    }
                    PayAttendanceBo attendance = new PayAttendanceBo();
                    //attendance.setTenantId(LoginHelper.getTenantId());
                    attendance.setTenantId(tenantId);
                    attendance.setKaoqinYearMonth(date);
                    attendance.setEmpName(wname);
                    attendance.setKaoqinjiNum(kaoqinType);

                    attendance.setEmployeeId(info.getEmployeeId());
                    attendance.setDeptId(info.getDeptId());
                    attendance.setDeptName(info.getDeptName());

                    String strday = date+"-"+days.get(j-3);
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                    Date day = sdf.parse(strday);
                    attendance.setKaoqinDate(day);

                    Cell cell = row1.getCell(j);
                    if (!(null==cell)){
                        String value = this.getCellValue(row1, j).toString();
                        // System.out.println("*************************************:"+value);
                        if(value!=null&&!value.trim().equals("")) {//判断非空或者非空串单元格
                            String[] times = value.split("\n");
                            /*  Date standard = new DateTime(strday + " 13:00:00");//以13点为分界线，改为去字典配置分界时间，去字典中去值*/
                            Date standard = new DateTime(strday + " " + dictService.getDictValue("pay_time_divid","noon_time"));//以13点为分界线
                            List<Date> ams = new ArrayList<>();//上午时间段内
                            List<Date> pms = new ArrayList<>();//下午时间短内
                            SimpleDateFormat punchTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            for(String  t:times){
                                Date time=  punchTime.parse(strday+" "+t+":00");
                                if(time.before(standard)){
                                    ams.add(time);
                                }else{
                                    pms.add(time);
                                }
                            }
                            //判断上下午时间段有几个值，对应存储
                            switch (ams.size()){
                                case 0:
                                    break;
                                case 1:
                                    if(ams.get(0).before(punchTime.parse(strday+" 10:30:00"))){  //上午只打了一次卡 过了上午10点半算下班卡
                                        attendance.setAmStartTime(ams.get(0));
                                    }else{
                                        attendance.setAmEndTime(ams.get(0));
                                    }
                                    break;
                                default:
                                    List<Date> amtimes = getDates(ams);
                                    attendance.setAmStartTime(amtimes.get(0));
                                    attendance.setAmEndTime(amtimes.get(1));
                                    break;
                            }
                            switch (pms.size()){
                                case 0:
                                    break;
                                case 1:
                                    if(pms.get(0).before(punchTime.parse(strday+" 16:30:00"))){  //下午只打了一次卡 过了下午四点半算下班卡
                                        attendance.setPmStartTime(pms.get(0));
                                    }else{
                                        attendance.setPmEndTime(pms.get(0));
                                    }
                                    break;
                                default:
                                    List<Date> pmtimes = getDates(pms);
                                    attendance.setPmStartTime(pmtimes.get(0));
                                    attendance.setPmEndTime(pmtimes.get(1));
                                    break;
                            }

                        }
                    }
                    attendances.add(attendance);
                }
            }
        }
        return attendances;
    }
    //获取一个月天数
    public static int getDaysOfMonth(String datestr) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM");
        Date date = format.parse(datestr);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }



}

