package com.ycwl.basic.controller.printer;


import com.ycwl.basic.annotation.IgnoreToken;
import com.ycwl.basic.integration.device.dto.device.DeviceV2DTO;
import com.ycwl.basic.integration.scenic.dto.scenic.ScenicV2DTO;
import com.ycwl.basic.mapper.SourceMapper;
import com.ycwl.basic.model.mobile.face.FaceRecognizeResp;
import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.faceSample.entity.FaceSampleEntity;
import com.ycwl.basic.model.pc.mp.MpConfigEntity;
import com.ycwl.basic.model.pc.printer.resp.PrinterResp;
import com.ycwl.basic.model.pc.scenic.req.ScenicReqQuery;
import com.ycwl.basic.model.pc.source.entity.SourceEntity;
import com.ycwl.basic.model.printer.req.TvCreateVirtualOrderRequest;
import com.ycwl.basic.pay.entity.PayResponse;
import com.ycwl.basic.repository.DeviceRepository;
import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.repository.ScenicRepository;
import com.ycwl.basic.service.pc.FaceService;
import com.ycwl.basic.service.pc.OrderService;
import com.ycwl.basic.service.printer.PrinterService;
import com.ycwl.basic.utils.ApiResponse;
import com.ycwl.basic.utils.WxMpUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
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 java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

@IgnoreToken
// 打印机大屏对接接口
@RestController
@RequestMapping("/printer/v1/tv")
@RequiredArgsConstructor
public class PrinterTvController {

    private final DeviceRepository deviceRepository;
    private final ScenicRepository scenicRepository;
    private final FaceRepository faceRepository;
    private final FaceService pcFaceService;
    private final SourceMapper sourceMapper;
    private final PrinterService printerService;
    private final OrderService orderService;

    /**
     * 获取景区列表
     *
     * @return 景区列表
     */
    @GetMapping("/scenic/list")
    public ApiResponse<List<ScenicV2DTO>> getScenicList() {
        ScenicReqQuery query = new ScenicReqQuery();
        query.setStatus("1"); // 只查询启用状态的景区
        query.setPageNum(1);
        query.setPageSize(1000);
        return ApiResponse.success(scenicRepository.list(query));
    }

    /**
     * 根据景区ID查询设备列表
     *
     * @param scenicId 景区ID
     * @return 设备列表
     */
    @GetMapping("/device/list")
    public ApiResponse<List<DeviceV2DTO>> getDeviceListByScenicId(@RequestParam Long scenicId) {
        List<DeviceV2DTO> result = deviceRepository.getAllDeviceByScenicId(scenicId);
        return ApiResponse.success(result);
    }

    @GetMapping("/{sampleId}/qrcode")
    public void getQrcode(@PathVariable("sampleId") Long sampleId, HttpServletResponse response) throws Exception {
        File qrcode = new File("qrcode_"+sampleId+".jpg");
        FaceSampleEntity faceSample = faceRepository.getFaceSample(sampleId);
        if (faceSample == null) {
            response.setStatus(404);
            return;
        }
        String targetPath = "pages/printer/from_sample";
        DeviceV2DTO device = deviceRepository.getDeviceBasic(faceSample.getDeviceId());
        if (device.getType().equals("AI_CAM")) {
            // AI_CAM，需要修改path
            targetPath = "pages/ai-cam/from_sample";
        }
        try {
            MpConfigEntity scenicMpConfig = scenicRepository.getScenicMpConfig(faceSample.getScenicId());
            WxMpUtil.generateUnlimitedWXAQRCode(scenicMpConfig.getAppId(), scenicMpConfig.getAppSecret(), targetPath, sampleId.toString(), qrcode);

            // 设置响应头
            response.setContentType("image/jpeg");
            response.setHeader("Content-Disposition", "inline; filename=\"" + qrcode.getName() + "\"");

            // 将二维码文件写入响应输出流
            try (FileInputStream fis = new FileInputStream(qrcode);
                 OutputStream os = response.getOutputStream()) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = fis.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
                os.flush();
            }
        } finally {
            // 删除临时文件
            if (qrcode.exists()) {
                qrcode.delete();
            }
        }
    }

    /**
     * 获取人脸绑定二维码
     * 生成小程序二维码，用于绑定人脸到用户账号
     *
     * @param faceId 人脸ID
     * @param response HTTP响应
     */
    @GetMapping("/face/{faceId}/qrcode")
    public void getFaceQrcode(@PathVariable("faceId") Long faceId, HttpServletResponse response) throws Exception {
        String url = pcFaceService.bindWxaCode(faceId);
        response.sendRedirect(url);
    }

    /**
     * 根据人脸ID查询图像素材
     *
     * @param faceId 人脸ID
     * @param type 素材类型（默认为2-图片）
     * @return 匹配的source记录
     */
    @GetMapping("/{faceId}/source")
    public ApiResponse<List<SourceEntity>> getSourceByFaceId(@PathVariable Long faceId, @RequestParam(name = "type", required = false, defaultValue = "2") Integer type) {
        List<SourceEntity> sources = sourceMapper.listSourceByFaceRelation(faceId, type);
        return ApiResponse.success(sources);
    }

    /**
     * 打印机大屏人脸识别
     * 上传照片，在景区人脸库中搜索匹配的人脸样本，返回识别结果
     *
     * 使用 USER_FACE_DB_NAME+scenicId 对人脸进行去重检测：
     * - 如果已存在相同人脸（打印机大屏用户，memberId=0），则返回已存在的 faceId
     * - 否则创建新的人脸记录并添加到人脸库
     *
     * @param file 人脸照片文件
     * @param scenicId 景区ID
     * @return 人脸识别结果
     */
    @PostMapping("/{scenicId}/faceRecognize")
    public ApiResponse<FaceRecognizeResp> faceRecognize(
            @RequestParam("file") MultipartFile file,
            @PathVariable Long scenicId) {
        // 复用 faceUpload 方法的去重逻辑
        // memberId=0L 表示打印机大屏用户，scene="tv" 为试点场景：仅执行识别/补救/落库/建关系
        FaceRecognizeResp resp = pcFaceService.faceUpload(file, scenicId, 0L, "tv");
        return ApiResponse.success(resp);
    }

    /**
     * 通过人脸样本ID重定向到人脸图片URL
     *
     * @param faceSampleId 人脸样本ID
     * @param response HTTP响应
     */
    @GetMapping("/faceSample/{faceSampleId}/url")
    public void redirectToFaceSampleUrl(@PathVariable Long faceSampleId, HttpServletResponse response) throws Exception {
        FaceSampleEntity faceSample = faceRepository.getFaceSample(faceSampleId);
        if (faceSample == null || faceSample.getFaceUrl() == null) {
            response.setStatus(404);
            return;
        }
        response.sendRedirect(faceSample.getFaceUrl());
    }

    /**
     * 通过人脸ID重定向到人脸图片URL
     *
     * @param faceId 人脸ID
     * @param response HTTP响应
     */
    @GetMapping("/face/{faceId}/url")
    public void redirectToFaceUrl(@PathVariable Long faceId, HttpServletResponse response) throws Exception {
        FaceEntity face = faceRepository.getFace(faceId);
        if (face == null || face.getFaceUrl() == null) {
            response.setStatus(404);
            return;
        }
        response.sendRedirect(face.getFaceUrl());
    }

    /**
     * 获取景区下的打印机列表
     *
     * @param scenicId 景区ID
     * @return 启用状态的打印机列表
     */
    @GetMapping("/printer/list")
    public ApiResponse<List<PrinterResp>> getPrinterListByScenicId(@RequestParam Long scenicId) {
        return ApiResponse.success(printerService.listByScenicId(scenicId));
    }

    /**
     * 批量创建虚拟用户订单
     * 传入faceSampleIds，自动查找关联的照片素材(type=2)，聚合为一笔订单、一次支付
     *
     * @param request 请求参数（含faceSampleIds列表）
     * @return 聚合订单结果
     */
    @PostMapping("/createVirtualOrder")
    public ApiResponse<Map<String, Object>> createVirtualOrder(@RequestBody TvCreateVirtualOrderRequest request) {
        if (request.getFaceSampleIds() == null || request.getFaceSampleIds().isEmpty()) {
            return ApiResponse.fail("faceSampleIds不能为空");
        }
        try {
            List<SourceEntity> sources = sourceMapper.listByFaceSampleIdsAndType(request.getFaceSampleIds(), 2);
            if (sources.isEmpty()) {
                return ApiResponse.fail("未找到关联的照片素材");
            }
            List<Long> sourceIds = sources.stream().map(SourceEntity::getId).toList();
            Map<String, Object> result = printerService.createBatchVirtualOrder(
                    sourceIds,
                    request.getScenicId(),
                    request.getPrinterId(),
                    request.getNeedEnhance(),
                    request.getPrintImgUrl(),
                    request.getNeedActualPayment()
            );
            return ApiResponse.success(result);
        } catch (Exception e) {
            return ApiResponse.fail(e.getMessage());
        }
    }

    /**
     * 查询订单支付状态
     *
     * @param orderId 订单ID
     * @return 支付状态信息
     */
    @GetMapping("/order/query")
    public ApiResponse<PayResponse> queryOrder(@RequestParam("orderId") Long orderId) {
        return ApiResponse.success(orderService.queryOrder(orderId));
    }

}
