package com.jeeplus.psimanage.dishManage.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.handler.context.SheetWriteHandlerContext;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeeplus.common.excel.ExcelOptions;
import com.jeeplus.common.excel.annotation.ExportMode;
import com.jeeplus.logging.annotation.ApiLog;
import com.jeeplus.logging.constant.enums.LogTypeEnum;
import com.jeeplus.psimanage.dishManage.domain.PsiDishLibrary;
import com.jeeplus.psimanage.dishManage.domain.PsiDishOrder;
import com.jeeplus.psimanage.dishManage.domain.PsiDishType;
import com.jeeplus.psimanage.dishManage.service.PsiDishOrderService;
import com.jeeplus.psimanage.dishManage.service.dto.PsiDishOrderExportDto;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;

/**
 * 点菜页面
 */
@RestController
@Api(tags = "点菜页面")
@RequestMapping(value = "/psi/dishOrder")
public class PsiDishOrderController {

    private static final String EXPORT_TITLE = "景聚庭订单导出";
    private static final int EXPORT_COLUMN_COUNT = 13;

    @Resource
    private PsiDishOrderService service;

    @ApiOperation(value = "查询有菜品的分类")
    @GetMapping("/typeList")
    public ResponseEntity<List<PsiDishType>> typeList() {
        return ResponseEntity.ok(service.typeList());
    }

    @ApiOperation(value = "查询菜品")
    @GetMapping("/dishList")
    public ResponseEntity<List<PsiDishLibrary>> dishList(@RequestParam(required = false) String typeId,
                                                         @RequestParam(required = false) String dishName) {
        return ResponseEntity.ok(service.dishList(typeId, dishName));
    }

    @ApiOperation(value = "订单列表")
    @GetMapping("/orderList")
    public ResponseEntity<IPage<PsiDishOrder>> orderList(Page<PsiDishOrder> page, PsiDishOrder info) {
        return ResponseEntity.ok(service.list(page, info));
    }

    @ApiLog(value = "导出订单数据", type = LogTypeEnum.EXPORT)
    @ApiOperation(value = "导出订单数据")
    @GetMapping("/exportFile")
    public void exportFile(Page<PsiDishOrder> page, PsiDishOrder info, ExcelOptions options, HttpServletResponse response) throws Exception {
        String fileName = options.getFilename();
        String sheetName = options.getSheetName();
        List<PsiDishOrderExportDto> result;
        if (ExportMode.current.equals(options.getMode())) {
            result = service.exportRecordList(page, info);
        } else if (ExportMode.selected.equals(options.getMode())) {
            result = service.exportRecordList(page, info).stream().filter(item ->
                    options.getSelectIds().contains(item.getId())
            ).collect(Collectors.toList());
        } else {
            page.setSize(-1);
            page.setCurrent(0);
            result = service.exportRecordList(page, info);
        }
        List<String> exportFields = options.getExportFields();
        exportDishOrderExcel(result, sheetName, fileName,
                exportFields == null || exportFields.isEmpty() ? null : exportFields, response);
    }

    private void exportDishOrderExcel(List<PsiDishOrderExportDto> result, String sheetName, String fileName,
                                      Collection<String> exportFields, HttpServletResponse response) throws Exception {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + encodedFileName + ".xlsx");

        int columnCount = exportFields == null ? EXPORT_COLUMN_COUNT : exportFields.size();
        ExcelWriterBuilder writerBuilder = EasyExcel.write(response.getOutputStream(), PsiDishOrderExportDto.class)
                .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
                .relativeHeadRowIndex(1)
                .registerWriteHandler(new HorizontalCellStyleStrategy(buildPlainHeadStyle(), buildPlainContentStyle()))
                .registerWriteHandler(new DishOrderExportSheetWriteHandler(EXPORT_TITLE, Math.max(columnCount, 1)));
        if (exportFields != null) {
            writerBuilder.includeColumnFieldNames(exportFields);
        }
        writerBuilder.sheet(sheetName).doWrite(result);
    }

    private WriteCellStyle buildPlainHeadStyle() {
        WriteCellStyle headStyle = new WriteCellStyle();
        headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        headStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        WriteFont headFont = new WriteFont();
        headFont.setBold(false);
        headStyle.setWriteFont(headFont);
        return headStyle;
    }

    private WriteCellStyle buildPlainContentStyle() {
        WriteCellStyle contentStyle = new WriteCellStyle();
        contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        return contentStyle;
    }

    private static class DishOrderExportSheetWriteHandler implements SheetWriteHandler {

        private final String title;
        private final int columnCount;

        DishOrderExportSheetWriteHandler(String title, int columnCount) {
            this.title = title;
            this.columnCount = columnCount;
        }

        @Override
        public void beforeSheetCreate(SheetWriteHandlerContext context) {
        }

        @Override
        public void afterSheetCreate(SheetWriteHandlerContext context) {
            WriteSheetHolder sheetHolder = context.getWriteSheetHolder();
            Sheet sheet = sheetHolder.getSheet();
            Workbook workbook = sheet.getWorkbook();
            Row titleRow = sheet.createRow(0);
            titleRow.setHeightInPoints(30F);
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellValue(title);
            titleCell.setCellStyle(createTitleStyle(workbook));
            if (columnCount > 1) {
                sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 0, 0, columnCount - 1));
            }
            sheet.createFreezePane(0, 2);
        }

        private CellStyle createTitleStyle(Workbook workbook) {
            CellStyle titleStyle = workbook.createCellStyle();
            titleStyle.setAlignment(HorizontalAlignment.CENTER);
            titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);
            Font titleFont = workbook.createFont();
            titleFont.setBold(true);
            titleFont.setFontHeightInPoints((short) 16);
            titleStyle.setFont(titleFont);
            return titleStyle;
        }
    }

    @ApiOperation(value = "订单详情")
    @GetMapping("/findOrderById")
    public ResponseEntity<PsiDishOrder> findOrderById(@RequestParam String id) {
        return ResponseEntity.ok(service.findOrderById(id));
    }

    @ApiOperation(value = "查询当前包房订单")
    @GetMapping("/currentOrder")
    public ResponseEntity<PsiDishOrder> currentOrder(@RequestParam String roomId) {
        return ResponseEntity.ok(service.currentOrder(roomId));
    }

    @ApiOperation(value = "取消订单")
    @GetMapping("/cancelOrder")
    public ResponseEntity<String> cancelOrder(@RequestParam String id) {
        return ResponseEntity.ok(service.cancelOrder(id));
    }

    @ApiOperation(value = "下单")
    @PostMapping("/submit")
    public ResponseEntity<String> submit(@RequestBody PsiDishOrder info) {
        return ResponseEntity.ok(service.submitOrder(info));
    }
}
