package com.writeoff.module.notification.controller;

import com.writeoff.common.api.ApiResponse;
import com.writeoff.common.api.PageResult;
import com.writeoff.common.exception.BusinessException;
import com.writeoff.common.exception.ErrorCodes;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.writeoff.module.export.dto.CreateExportTaskRequest;
import com.writeoff.module.export.service.ExportTaskService;
import com.writeoff.module.notification.dto.DispatchNotificationRequest;
import com.writeoff.module.notification.dto.AliyunSmsReceiptRequest;
import com.writeoff.module.notification.dto.NotificationReceiptRequest;
import com.writeoff.module.notification.model.NotificationTaskInfo;
import com.writeoff.module.notification.service.NotificationDispatchService;
import com.writeoff.security.DataScopeType;
import com.writeoff.security.RequirePermission;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/notifications")
public class NotificationDispatchController {
    private final NotificationDispatchService notificationDispatchService;
    private final ExportTaskService exportTaskService;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public NotificationDispatchController(NotificationDispatchService notificationDispatchService,
                                           ExportTaskService exportTaskService) {
        this.notificationDispatchService = notificationDispatchService;
        this.exportTaskService = exportTaskService;
    }

    @PostMapping("/tasks/export")
    @RequirePermission(value = "notification.task.read", dataScope = DataScopeType.TENANT, auditAction = "NOTIFICATION_TASK_EXPORT")
    public ApiResponse<Map<String, Object>> exportTasks(@RequestBody @Valid CreateExportTaskRequest request) {
        request.setTaskCode("NOTIFICATION_TASK_EXPORT");
        request.setBizType("NOTIFICATION_TASK");
        return ApiResponse.success(exportTaskService.create(request));
    }

    @PostMapping("/dispatch")
    @RequirePermission(value = "notification.dispatch", dataScope = DataScopeType.TENANT, auditAction = "NOTIFICATION_DISPATCH")
    public ApiResponse<Map<String, Object>> dispatch(@RequestBody @Valid DispatchNotificationRequest request) {
        return ApiResponse.success(notificationDispatchService.dispatch(request));
    }

    @GetMapping("/tasks")
    @RequirePermission(value = "notification.task.read", dataScope = DataScopeType.TENANT, auditAction = "NOTIFICATION_TASK_LIST")
    public ApiResponse<PageResult<NotificationTaskInfo>> listTasks(
            @RequestParam(value = "pageNo", required = false) Integer pageNo,
            @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        return ApiResponse.success(notificationDispatchService.listTasks(pageNo, pageSize));
    }

    @PostMapping("/receipts")
    @RequirePermission(value = "notification.dispatch", dataScope = DataScopeType.TENANT, auditAction = "NOTIFICATION_RECEIPT_INGEST")
    public ApiResponse<Map<String, Object>> receipt(@RequestBody @Valid NotificationReceiptRequest request) {
        return ApiResponse.success(notificationDispatchService.ingestReceipt(request));
    }

    @PostMapping("/receipts/webhook")
    public ApiResponse<Map<String, Object>> receiptWebhook(@RequestBody @Valid NotificationReceiptRequest request,
                                                           @RequestHeader(value = "X-Receipt-Timestamp", required = false) String timestamp,
                                                           @RequestHeader(value = "X-Receipt-Signature", required = false) String signature) {
        return ApiResponse.success(notificationDispatchService.ingestReceiptWebhook(request, timestamp, signature));
    }

    @PostMapping("/receipts/providers/aliyun-sms")
    public ApiResponse<Map<String, Object>> aliyunSmsReceipt(@RequestBody(required = false) String body,
                                                             HttpServletRequest httpServletRequest) {
        List<AliyunSmsReceiptRequest> requests = parseAliyunSmsReceiptRequests(body, httpServletRequest);
        return ApiResponse.success(notificationDispatchService.ingestAliyunSmsReceipts(requests));
    }

    private List<AliyunSmsReceiptRequest> parseAliyunSmsReceiptRequests(String body, HttpServletRequest request) {
        String raw = body == null ? "" : body.trim();
        try {
            if (!raw.isEmpty()) {
                if (raw.startsWith("[")) {
                    List<AliyunSmsReceiptRequest> list = objectMapper.readValue(raw, new TypeReference<List<AliyunSmsReceiptRequest>>() {});
                    return list == null ? new ArrayList<AliyunSmsReceiptRequest>() : list;
                }
                if (raw.startsWith("{")) {
                    AliyunSmsReceiptRequest single = objectMapper.readValue(raw, AliyunSmsReceiptRequest.class);
                    List<AliyunSmsReceiptRequest> list = new ArrayList<AliyunSmsReceiptRequest>();
                    list.add(single);
                    return list;
                }
            }
        } catch (Exception ex) {
            throw new BusinessException(ErrorCodes.VALIDATION_ERROR, "阿里云短信回执请求体格式非法");
        }

        Map<String, String[]> parameterMap = request == null ? new LinkedHashMap<String, String[]>() : request.getParameterMap();
        if (parameterMap == null || parameterMap.isEmpty()) {
            throw new BusinessException(ErrorCodes.VALIDATION_ERROR, "阿里云短信回执内容不能为空");
        }
        AliyunSmsReceiptRequest single = new AliyunSmsReceiptRequest();
        single.setBizId(firstParam(parameterMap, "biz_id", "bizId"));
        single.setOutId(firstParam(parameterMap, "out_id", "outId"));
        single.setPhoneNumber(firstParam(parameterMap, "phone_number", "phoneNumber"));
        single.setErrCode(firstParam(parameterMap, "err_code", "errCode"));
        single.setErrMsg(firstParam(parameterMap, "err_msg", "errMsg"));
        String success = firstParam(parameterMap, "success", "Success");
        if (success != null && success.trim().length() > 0) {
            single.setSuccess(Boolean.valueOf(success.trim()));
        }
        single.setReceiveDate(firstParam(parameterMap, "report_time", "receiveDate", "receive_time"));
        List<AliyunSmsReceiptRequest> list = new ArrayList<AliyunSmsReceiptRequest>();
        list.add(single);
        return list;
    }

    private String firstParam(Map<String, String[]> parameterMap, String... names) {
        if (parameterMap == null || names == null) {
            return null;
        }
        for (String name : names) {
            String[] values = parameterMap.get(name);
            if (values != null && values.length > 0 && values[0] != null) {
                return values[0];
            }
        }
        return null;
    }
}
