package io.renren.modules.admin.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import io.renren.modules.admin.entity.AttendersviewEntity;
import io.renren.modules.admin.entity.AttendersEntity;
import io.renren.modules.admin.entity.MemberEntity;
import io.renren.modules.admin.service.AttendersviewService;
import io.renren.modules.admin.service.MeetingService;
import io.renren.modules.admin.service.AttendersService;
import io.renren.modules.admin.service.MemberService;
import io.renren.modules.sys.controller.AbstractController;
import io.renren.common.utils.ExcelData;
import io.renren.common.utils.ExcelUtils;
import io.renren.common.utils.MyUtils;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.common.validator.ValidatorUtils;
import io.renren.common.validator.group.AddGroup;
import io.renren.common.validator.group.UpdateGroup;

/**
 *
 * @author huwhois
 * @email huwhois@163.com
 * @date 2020-12-11 09:44:26
 */
@RestController
@RequestMapping("admin/attenders")
public class AttendersController extends AbstractController {
    @Autowired
    private AttendersService attendersService;
    @Autowired
    private AttendersviewService attendersviewService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private MeetingService meetingService;


    @Value("${file.datapath}")
    private String dataPath; // 读取配置文件中的指定目录

    @Value("${file.uploadFolder}")
    private String uploadFolder; // 读取配置文件中的指定目录

    private SimpleDateFormat sdfDate = new SimpleDateFormat(" yyyy-MM-dd HH:mm:ss ");

    /**
     * 列表
     */
    @GetMapping("/list")
    @RequiresPermissions("admin:attenders:list")
    public R list(@RequestParam Map<String, Object> params) {
        if (!params.containsKey("meetingId")) {
            return R.error("会议id不可为空");
        }

        PageUtils page = attendersviewService.queryPage(params);

        return R.ok().put("page", page);
    }

    /**
     * 信息
     */
    @GetMapping("/info/{id}")
    @RequiresPermissions("admin:attenders:info")
    public R info(@PathVariable("id") Long id) {
        AttendersviewEntity attenders = attendersviewService.getById(id);

        return R.ok().put("attenders", attenders);
    }

    /**
     * 保存
     */
    @PostMapping("/save")
    @RequiresPermissions("admin:attenders:save")
    public R save(@RequestBody AttendersviewEntity attendersform) {
        ValidatorUtils.validateEntity(attendersform, AddGroup.class);
        Long meetingId = attendersform.getMeetingId();
        if (meetingId == 0L) {
            return R.error("会议id不可为空");
        }

        addAttenders(attendersform);

        return R.ok();
    }

    public boolean addAttenders(AttendersviewEntity attendersform) {
        try {
            String symbol = MyUtils.md5(attendersform.getTruename() + attendersform.getPhone());

            MemberEntity member = memberService.getBySymbol(symbol);

            // 存会员表(个人信息, 开票信息)
            if (member == null) {
                member = new MemberEntity();
                member.setTruename(attendersform.getTruename());
                member.setPhone(attendersform.getPhone());
            }
            member.setOrganization(attendersform.getOrganization());
            member.setPosition(attendersform.getPosition());
            member.setEmail(attendersform.getEmail());
            member.setSex(attendersform.getSex());
            member.setRemark(attendersform.getRemark());
            member.setTaxType(attendersform.getTaxType());
            member.setTaxTitle(attendersform.getTaxTitle());
            member.setTaxNumber(attendersform.getTaxNumber());
            member.setCompanyAddress(attendersform.getCompanyAddress());
            member.setCompanyPhone(attendersform.getCompanyPhone());
            member.setBankAccount(attendersform.getBankAccount());
            member.setMailingAddress(attendersform.getMailingAddress());
            member.setPostcode(attendersform.getPostcode());

            if (member.getId() == null || member.getId() == 0L) {
                memberService.saveMember(member);
            } else {
                memberService.updateMember(member);
            }

            // 存参会信息
            AttendersEntity attenders = attendersService.getByMMId(member.getId(), attendersform.getMeetingId());
            if (attenders == null) {
                attenders = new AttendersEntity();
                attenders.setMemberId(member.getId());
                attenders.setMeetingId(attendersform.getMeetingId());
            }

            attenders.setMemberType(attendersform.getMemberType());
            attenders.setFeeType(attendersform.getFeeType());
            attenders.setPaperType(attendersform.getPaperType());
            attenders.setIsReport(attendersform.getIsReport());
            attenders.setReportTitle(attendersform.getReportTitle());
            attenders.setHotelType(attendersform.getHotelType());
            attenders.setRoomType(attendersform.getRoomType());
            attenders.setCheckInDate(attendersform.getCheckInDate());
            attenders.setCheckOutDate(attendersform.getCheckOutDate());
            attenders.setPayType(attendersform.getPayType());
            attenders.setIsPay(attendersform.getIsPay());
            attenders.setMoney(attendersform.getMoney());
            attenders.setCreateTime(new Date());

            attendersService.save(attenders);
        } catch (Exception e) {
            return false;
        }

        return true;
    }

    /**
     * 修改
     */
    @PostMapping("/update")
    @RequiresPermissions("admin:attenders:update")
    public R update(@RequestBody AttendersviewEntity attendersform) {
        ValidatorUtils.validateEntity(attendersform, UpdateGroup.class);
        Long meetingId = attendersform.getMeetingId();
        if (meetingId == 0L) {
            return R.error("会议id不可为空");
        }
        MemberEntity member = memberService.getById(attendersform.getMemberId());
        if (member == null) {
            return R.error("会员不存在");
        }
        member.setTruename(attendersform.getTruename());
        member.setOrganization(attendersform.getOrganization());
        member.setPosition(attendersform.getPosition());
        member.setPhone(attendersform.getPhone());
        member.setEmail(attendersform.getEmail());
        member.setSex(attendersform.getSex());
        member.setRemark(attendersform.getRemark());
        member.setTaxType(attendersform.getTaxType());
        member.setTaxTitle(attendersform.getTaxTitle());
        member.setTaxNumber(attendersform.getTaxNumber());
        member.setCompanyAddress(attendersform.getCompanyAddress());
        member.setCompanyPhone(attendersform.getCompanyPhone());
        member.setBankAccount(attendersform.getBankAccount());
        member.setMailingAddress(attendersform.getMailingAddress());
        member.setPostcode(attendersform.getPostcode());

        memberService.updateMember(member);

        AttendersEntity attenders = attendersService.getById(attendersform.getId());
        if (attenders == null) {
            return R.error("参会人员不存在");
        }
        attenders.setMemberId(attendersform.getMemberId());
        attenders.setMeetingId(attendersform.getMeetingId());
        attenders.setMemberType(attendersform.getMemberType());
        attenders.setFeeType(attendersform.getFeeType());
        attenders.setPaperType(attendersform.getPaperType());
        attenders.setIsReport(attendersform.getIsReport());
        attenders.setReportTitle(attendersform.getReportTitle());
        attenders.setHotelType(attendersform.getHotelType());
        attenders.setRoomType(attendersform.getRoomType());
        attenders.setCheckInDate(attendersform.getCheckInDate());
        attenders.setCheckOutDate(attendersform.getCheckOutDate());
        attenders.setPayType(attendersform.getPayType());
        attenders.setIsPay(attendersform.getIsPay());
        attenders.setMoney(attendersform.getMoney());
        attendersService.updateById(attenders);

        return R.ok();
    }

    /**
     * 删除
     */
    @PostMapping("/delete")
    @RequiresPermissions("admin:attenders:delete")
    public R delete(@RequestBody Long[] ids) {
        attendersService.removeByIds(Arrays.asList(ids));

        return R.ok();
    }

    /**
     * listall
     */
    @GetMapping("/listall/{mid}")
    @RequiresPermissions("admin:attenders:list")
    public R listall(@PathVariable("mid") Long mid) {
        List<AttendersviewEntity> list = attendersviewService.listall(mid,
                new String[] { "id", "truename", "organization", "phone", "meeting_id" });
        return R.ok().put("list", list);
    }

    /**
     * 修改是否缴费
     */
    @RequestMapping("/ispay")
    @RequiresPermissions("admin:attenders:update")
    public R updateIsPay(@RequestBody Map<String, Object> params) {
        Long aid = Long.valueOf((Integer) params.get("aid"));
        Integer isPay = (Integer) params.get("isPay");

        AttendersEntity attenders = attendersService.getById(aid);
        if (attenders == null) {
            return R.error("用户不存在");
        }
        attenders.setIsPay(isPay);

        attendersService.updateById(attenders);

        return R.ok();
    }

    /**
     * 导出报名参会名单
     * 
     * @param response
     * @param params
     * @throws Exception
     */
    @GetMapping("/export")
    @RequiresPermissions("admin:attenders:list")
    public void exportExcel(HttpServletResponse response, @RequestParam Map<String, Object> params) throws Exception {
        if (!params.containsKey("meetingId")) {
            throw new Exception("会议id不可为空");
        }
        
        Long meetingId = Long.valueOf(params.get("meetingId").toString());
        if (!meetingService.meetingExist(meetingId)) {
            throw new Exception("此会议不存在");
        }

        String meetingName = params.containsKey("meetingName") ? params.get("meetingName").toString() : "";

        ExcelData data = new ExcelData();
        data.setName(meetingName + "参会名单");
        // 添加表头
        List<String> titles = new ArrayList<String>();
        titles.add("id");
        titles.add("姓名");
        titles.add("性别");
        titles.add("单位名称");
        titles.add("职务");
        titles.add("电话");
        titles.add("联系邮箱");
        titles.add("开票类型");
        titles.add("发票抬头");
        titles.add("税号");
        titles.add("单位地址");
        titles.add("单位电话");
        titles.add("开户行及账号");
        titles.add("邮寄地址");
        titles.add("邮编");
        titles.add("备注");
        titles.add("用户类型");
        titles.add("费用类型");
        titles.add("论文");
        titles.add("是否有报告");
        titles.add("报告题目");
        titles.add("酒店");
        titles.add("房型");
        titles.add("入住时间");
        titles.add("离店时间");
        titles.add("付款方式");
        titles.add("是否缴费");
        titles.add("金额");
        data.setTitles(titles);

        // 添加列
        List<List<Object>> rows = new ArrayList<List<Object>>();
        List<Object> row = null;

        List<AttendersviewEntity> list = attendersviewService.listall(meetingId);

        for (AttendersviewEntity aEntity : list) {
            row = new ArrayList<Object>();
            row.add(aEntity.getId());
            row.add(aEntity.getTruename());
            if (aEntity.getSex() == 1) {
                row.add("男");
            } else if (aEntity.getSex() == 2) {
                row.add("女");
            } else {
                row.add("未知");
            }
            row.add(aEntity.getOrganization());
            row.add(aEntity.getPosition());
            row.add(aEntity.getPhone());
            row.add(aEntity.getEmail());
            row.add(aEntity.getTaxType() == 2 ? "专票" : "普票");
            row.add(aEntity.getTaxTitle());
            row.add(aEntity.getTaxNumber());
            row.add(aEntity.getCompanyAddress());
            row.add(aEntity.getCompanyPhone());
            row.add(aEntity.getBankAccount());
            row.add(aEntity.getMailingAddress());
            row.add(aEntity.getPostcode());
            row.add(aEntity.getRemark());
            row.add(aEntity.getMemberType());
            row.add(aEntity.getFeeType() == 2 ? "学生" : "普通");
            row.add(aEntity.getPaperType());
            row.add(aEntity.getIsReport() == 1 ? "是" : "否");
            row.add(aEntity.getReportTitle());
            row.add(aEntity.getHotelType());
            row.add(aEntity.getRoomType());
            row.add(aEntity.getCheckInDate());
            row.add(aEntity.getCheckOutDate());
            row.add(aEntity.getPayType() == 2 ? "汇款" : "现场缴费");
            row.add(aEntity.getIsPay() == 1 ? "已缴费" : "未缴费");
            row.add(aEntity.getMoney());
            rows.add(row);
            row = null;
        }
        data.setRows(rows);
        SimpleDateFormat fdate = new SimpleDateFormat("yyyyMMddHHmmss");
        String fileName = fdate.format(new Date()) + ".xlsx";

        // 告诉浏览器用什么软件可以打开此文件
        response.setHeader("content-Type", "application/vnd.ms-excel");
        // 下载文件的默认名称
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
        // response.setHeader("Content-Disposition", "attachment;filename="+fileName);

        ExcelUtils.exportExcel(data, response.getOutputStream());
    }

    /**
     * 参会名单导入
     * 
     * @param file
     * @param meetingId
     * @return
     * @throws Exception
     */
    @PostMapping("import")
    @RequiresPermissions("admin:attenders:save")
    public R importExcel(@RequestParam("file") MultipartFile file, @RequestParam("meetingId") Long meetingId) {
        if (meetingId == 0L) {
            return R.error("会议id不可为空");
        }
        if (file.isEmpty()) {
            return R.error("error,file is empty!");
        }
        if (ExcelUtils.isExcel(file) == false) {
            return R.error("error,file is not excel!");
        }

        Map<String, Integer> statistics = new HashMap<>();
        List<AttendersviewEntity> successList = new ArrayList<>();
        List<AttendersviewEntity> failList = new ArrayList<>();

        Workbook workbook = ExcelUtils.createWorkbook(file);
        if (workbook != null) {
            // 获取工作表
            Sheet sheet = workbook.getSheetAt(0);
            // 获取sheet中第一行行号
            int firstRowNum = sheet.getFirstRowNum();
            // 获取sheet中最后一行行号
            int lastRowNum = sheet.getLastRowNum();
            // 循环插入数据
            int failNum = 0;
            int totalNum = 0;
            for (int i = firstRowNum + 1; i <= lastRowNum; i++) { // 标题的下一行开始
                totalNum++;
                Row row = sheet.getRow(i);
                if (ExcelUtils.isEmptyRow(row) == false) {
                    String name = ExcelUtils.getVal(row.getCell(1));
                    String sex = ExcelUtils.getVal(row.getCell(2));
                    String organization = ExcelUtils.getVal(row.getCell(3));
                    String position = ExcelUtils.getVal(row.getCell(4));
                    String phone = ExcelUtils.getVal(row.getCell(5));
                    String email = ExcelUtils.getVal(row.getCell(6));
                    String tax_type = ExcelUtils.getVal(row.getCell(7));
                    String tax_ttitle = ExcelUtils.getVal(row.getCell(8));
                    String tax_number = ExcelUtils.getVal(row.getCell(9));
                    String company_address = ExcelUtils.getVal(row.getCell(10));
                    String company_phone = ExcelUtils.getVal(row.getCell(11));
                    String bank_account = ExcelUtils.getVal(row.getCell(12));
                    String mailing_address = ExcelUtils.getVal(row.getCell(13));
                    String postcode = ExcelUtils.getVal(row.getCell(14));
                    String remark = ExcelUtils.getVal(row.getCell(15));
                    String memberType = ExcelUtils.getVal(row.getCell(16));
                    String fee_id = ExcelUtils.getVal(row.getCell(17));
                    String paper_type = ExcelUtils.getVal(row.getCell(18));
                    String is_report = ExcelUtils.getVal(row.getCell(19));
                    String report_title = ExcelUtils.getVal(row.getCell(20));
                    String hotel_type = ExcelUtils.getVal(row.getCell(21));
                    String room_type = ExcelUtils.getVal(row.getCell(22));
                    String check_in_date = ExcelUtils.getVal(row.getCell(23));
                    String check_out_date = ExcelUtils.getVal(row.getCell(24));
                    String payment = ExcelUtils.getVal(row.getCell(25));
                    String isPay = ExcelUtils.getVal(row.getCell(26));
                    String money = ExcelUtils.getVal(row.getCell(27));

                    AttendersviewEntity attendersInfo = new AttendersviewEntity();

                    attendersInfo.setMeetingId(meetingId);
                    attendersInfo.setTruename(name);
                    attendersInfo.setPhone(phone);
                    attendersInfo.setSex(Integer.valueOf(sex));
                    attendersInfo.setOrganization(organization);
                    attendersInfo.setPosition(position);
                    attendersInfo.setEmail(email);
                    attendersInfo.setTaxType(Integer.valueOf(tax_type));
                    attendersInfo.setTaxTitle(tax_ttitle);
                    attendersInfo.setTaxNumber(tax_number);
                    attendersInfo.setCompanyAddress(company_address);
                    attendersInfo.setCompanyPhone(company_phone);
                    attendersInfo.setBankAccount(bank_account);
                    attendersInfo.setMailingAddress(mailing_address);
                    attendersInfo.setPostcode(postcode);
                    attendersInfo.setRemark(remark);
                    int memberTypeInt = StringUtils.isBlank(memberType) ? 0 : Integer.valueOf(memberType);
                    attendersInfo.setMemberType(memberTypeInt);
                    attendersInfo.setFeeType(Integer.valueOf(fee_id));
                    attendersInfo.setPaperType(Integer.valueOf(paper_type));
                    attendersInfo.setIsReport(Integer.valueOf(is_report));
                    attendersInfo.setReportTitle(report_title);
                    attendersInfo.setHotelType(Integer.valueOf(hotel_type));
                    attendersInfo.setRoomType(Integer.valueOf(room_type));
                    try {
                        attendersInfo.setCheckInDate(sdfDate.parse(check_in_date));
                        attendersInfo.setCheckInDate(sdfDate.parse(check_out_date));
                    } catch (Exception e) {
                        attendersInfo.setCheckInDate(null);
                        attendersInfo.setCheckInDate(null);
                    }

                    attendersInfo.setPayType(Integer.valueOf(payment));
                    attendersInfo.setIsPay(Integer.valueOf(isPay));
                    attendersInfo.setMoney(BigDecimal.valueOf(Double.valueOf(money.toString())));

                    if (StringUtils.isBlank(name)) {
                        attendersInfo.setRemark(attendersInfo.getRemark() + "==>姓名不能为空");
                        failList.add(attendersInfo);
                        failNum++;
                    } else if (StringUtils.isBlank(phone) || !MyUtils.checkPhone(phone)) {
                        attendersInfo.setRemark(attendersInfo.getRemark() + "==>电话格式不正确");
                        failList.add(attendersInfo);
                        failNum++;
                    } else {
                        successList.add(attendersInfo);
                    }
                }
            }
            doImport(successList, failList);
            statistics.put("total", totalNum);
            statistics.put("succes", totalNum - failNum);
            statistics.put("fail", failNum);
        }

        return R.ok("上传成功!").put("statistics", statistics);
    }

    @Async
    public void doImport(List<AttendersviewEntity> successList, List<AttendersviewEntity> failList) {
        for (AttendersviewEntity attendersInfo : successList) {
            try {
                addAttenders(attendersInfo);
            } catch (Exception e) {
                e.printStackTrace();
                attendersInfo.setRemark(attendersInfo.getRemark() + " 导入错误原因:未知");
                failList.add(attendersInfo);
            }
        }

        ExcelData data = new ExcelData();
        data.setName("error");
        // 添加表头
        List<String> titles = new ArrayList<String>();
        titles.add("id");
        titles.add("姓名");
        titles.add("性别");
        titles.add("单位名称");
        titles.add("职务");
        titles.add("电话");
        titles.add("联系邮箱");
        titles.add("开票类型");
        titles.add("发票抬头");
        titles.add("税号");
        titles.add("单位地址");
        titles.add("单位电话");
        titles.add("开户行及账号");
        titles.add("邮寄地址");
        titles.add("邮编");
        titles.add("备注");
        titles.add("用户类型");
        titles.add("费用类型");
        titles.add("论文");
        titles.add("是否有报告");
        titles.add("报告题目");
        titles.add("酒店");
        titles.add("房型");
        titles.add("入住时间");
        titles.add("离店时间");
        titles.add("付款方式");
        titles.add("是否缴费");
        titles.add("金额");
        data.setTitles(titles);

        // 新增列
        List<List<Object>> rows = new ArrayList<List<Object>>();
        List<Object> row = null;

        // SimpleDateFormat lastdate=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int i = 1;
        for (AttendersviewEntity attender : failList) {
            row = new ArrayList<Object>();
            row.add(i);
            row.add(attender.getTruename());
            row.add(attender.getSex());
            row.add(attender.getOrganization());
            row.add(attender.getPosition());
            row.add(attender.getPhone());
            row.add(attender.getEmail());
            row.add(attender.getTaxType());
            row.add(attender.getTaxTitle());
            row.add(attender.getTaxNumber());
            row.add(attender.getCompanyAddress());
            row.add(attender.getCompanyPhone());
            row.add(attender.getBankAccount());
            row.add(attender.getMailingAddress());
            row.add(attender.getPostcode());
            row.add(attender.getRemark());
            row.add(attender.getMemberType());
            row.add(attender.getFeeType());
            row.add(attender.getPaperType());
            row.add(attender.getIsReport());
            row.add(attender.getReportTitle());
            row.add(attender.getHotelType());
            row.add(attender.getRoomType());
            row.add(attender.getCheckInDate());
            row.add(attender.getCheckOutDate());
            row.add(attender.getPayType());
            row.add(attender.getIsPay());
            row.add(attender.getMoney());

            rows.add(row);
            row = null;
            i++;
        }

        data.setRows(rows);

        try {
            Long userId = getUserId();
            String fileName = "attenders_" + userId + ".xlsx";
            String filePath = "/uploads/fails/" + fileName;
            String savePath = dataPath + filePath;

            OutputStream os = new FileOutputStream(savePath);
            ExcelUtils.exportExcel(data, os);

            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 导出最近上传出租哦文件
     * @param response
     */
    @GetMapping("downloadfails")
    @RequiresPermissions("admin:attenders:save")
    public void downloadFailFile(HttpServletResponse response) {
        Long userId = getUserId();
        String filePath = dataPath + "/uploads/fails/attenders_" + userId + ".xlsx";
        
        try {
            File file = new File(filePath);
            if (file.exists()) {
                InputStream fis = new BufferedInputStream(new FileInputStream(file));
                byte[] buffer = new byte[fis.available()];
                fis.read(buffer);
                fis.close();

                response.reset();
                SimpleDateFormat fdate = new SimpleDateFormat("yyyyMMddHHmmss");
                String fileName = fdate.format(new Date()) + ".xlsx";
                // 告诉浏览器用什么软件可以打开此文件
                response.setHeader("content-Type", "application/vnd.ms-excel");
                // 下载文件的默认名称
                response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
                OutputStream os = new BufferedOutputStream(response.getOutputStream());
                os.write(buffer);
                os.flush();
                os.close();
            } else {
                response.sendError(HttpServletResponse.SC_NOT_FOUND, "没有最近出错文件");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e1){
            e1.printStackTrace();
        } catch (IOException e2){
            e2.printStackTrace();
        }
    }
}
