package com.usky.issue.controller.api;

import com.usky.common.core.bean.ApiResult;
import com.usky.issue.service.CloudAuthService;
import com.usky.issue.service.CloudConfigService;
import com.usky.issue.service.CloudSyncReceiveService;
import com.usky.issue.service.constant.CloudIntegrationConstants;
import com.usky.issue.service.vo.CloudConnectionTestResponse;
import com.usky.issue.service.vo.SyncPacket;
import com.usky.issue.service.vo.SyncPollRequest;
import com.usky.issue.service.vo.SyncResponse;
import com.usky.issue.service.util.CredentialMaskUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
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.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 云平台集成 API（供本地服务器调用：连通性测试 + 双向同步）
 *
 * @author fyc
 * @date 2026-06-08
 */
@Slf4j
@RestController
@RequestMapping("/cloud/integration")
public class CloudIntegrationApiController {

    @Autowired
    private CloudConfigService cloudConfigService;
    @Autowired
    private CloudAuthService cloudAuthService;
    @Autowired
    private CloudSyncReceiveService cloudSyncReceiveService;

    /**
     * 网络层探测
     */
    @GetMapping("/ping")
    public String ping() {
        return "PONG";
    }

    /**
     * 认证层 + 租户层检测
     */
    @GetMapping("/auth-check")
    public ResponseEntity<String> authCheck(
            @RequestHeader(value = CloudIntegrationConstants.HEADER_API_KEY, required = false) String apiKey,
            @RequestParam Integer tenantId) {
        if (!cloudAuthService.validateToken(apiKey, tenantId)) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("AUTH_INVALID");
        }
        CloudConnectionTestResponse tenantResult = cloudConfigService.validateTenantConnection(tenantId);
        if (!tenantResult.isSuccess()) {
            return ResponseEntity.ok(CloudIntegrationConstants.AUTH_CHECK_TENANT_MISSING);
        }
        return ResponseEntity.ok(CloudIntegrationConstants.AUTH_CHECK_VALID);
    }

    /**
     * 连通性测试入口（兼容旧调用方式）
     */
    @PostMapping("/testConnection")
    public ApiResult<CloudConnectionTestResponse> testConnection(
            @RequestHeader(value = CloudIntegrationConstants.HEADER_TENANT_ID, required = false) String tenantIdHeader,
            @RequestHeader(value = CloudIntegrationConstants.HEADER_API_KEY, required = false) String apiKey) {
        Integer tenantId = parseTenantId(tenantIdHeader);
        log.info("[连接测试-云端] 收到请求 tenantIdHeader={}, tenantId={}, apiKey={}",
                tenantIdHeader, tenantId, CredentialMaskUtil.mask(apiKey));

        if (tenantId != null && !cloudAuthService.validateToken(apiKey, tenantId)) {
            log.warn("[连接测试-云端] 认证失败 tenantId={}, apiKey={}", tenantId, CredentialMaskUtil.mask(apiKey));
            CloudConnectionTestResponse response = new CloudConnectionTestResponse();
            response.setSuccess(false);
            response.setConnectionStatus(2);
            response.setMessage(CloudIntegrationConstants.MSG_AUTH_INVALID);
            response.setNetworkReachable(true);
            response.setAuthValid(false);
            response.setTenantExists(false);
            return ApiResult.success(response);
        }
        CloudConnectionTestResponse response = cloudConfigService.validateTenantConnection(tenantId);
        log.info("[连接测试-云端] 租户校验 success={}, message={}", response.isSuccess(), response.getMessage());
        response.setNetworkReachable(true);
        response.setAuthValid(tenantId == null || cloudAuthService.validateToken(apiKey, tenantId));
        response.setTenantExists(response.isSuccess());
        log.info("[连接测试-云端] 返回 success={}, authValid={}, tenantExists={}, message={}",
                response.isSuccess(), response.getAuthValid(), response.getTenantExists(), response.getMessage());
        return ApiResult.success(response);
    }

    /**
     * 接收本地推送数据（本地→云端）
     */
    @PostMapping("/sync/receive")
    public SyncResponse receive(
            @RequestHeader(value = CloudIntegrationConstants.HEADER_API_KEY, required = false) String apiKey,
            @RequestHeader(value = CloudIntegrationConstants.HEADER_SIGN, required = false) String sign,
            @RequestBody SyncPacket packet) {

        if (!cloudAuthService.validate(apiKey, sign, packet)) {
            return SyncResponse.builder().success(false).message("认证失败或请求已过期").build();
        }
        if (!cloudSyncReceiveService.validateTenant(packet.getTenantId())) {
            return SyncResponse.builder().success(false).message("租户不存在或已停用").build();
        }
        try {
            int count = cloudSyncReceiveService.batchUpsert(packet);
            return SyncResponse.builder()
                    .success(true)
                    .message("接收成功")
                    .acceptedCount(count)
                    .confirmedVersion(packet.getBatchVersion())
                    .build();
        } catch (Exception e) {
            return SyncResponse.builder().success(false).message("写入失败:" + e.getMessage()).build();
        }
    }

    /**
     * 下发数据轮询（云端→本地），POST 供网关/offline-api 路由（与 testConnection 一致）
     */
    @PostMapping("/sync/poll")
    public ApiResult<SyncPacket> pollPost(
            @RequestHeader(value = CloudIntegrationConstants.HEADER_API_KEY, required = false) String apiKey,
            @RequestBody SyncPollRequest request) {
        return doPoll(apiKey, request.getTenantId(), request.getTableName(),
                request.getLastVersion(), request.isForceBackfill());
    }

    /**
     * 下发数据轮询（GET 兼容旧调用）
     */
    @GetMapping("/sync/poll")
    public ApiResult<SyncPacket> poll(
            @RequestHeader(value = CloudIntegrationConstants.HEADER_API_KEY, required = false) String apiKey,
            @RequestParam String tenantId,
            @RequestParam String tableName,
            @RequestParam(required = false) Long lastVersion,
            @RequestParam(required = false, defaultValue = "false") boolean forceBackfill) {
        return doPoll(apiKey, tenantId, tableName, lastVersion, forceBackfill);
    }

    private ApiResult<SyncPacket> doPoll(String apiKey, String tenantId, String tableName,
                                         Long lastVersion, boolean forceBackfill) {
        if (!cloudAuthService.validateToken(apiKey, Integer.valueOf(tenantId))) {
            log.warn("[poll] 认证失败 tenantId={}, tableName={}", tenantId, tableName);
            return ApiResult.error(CloudIntegrationConstants.MSG_POLL_AUTH_FAILED);
        }
        log.info("[poll] tenantId={}, tableName={}, lastVersion={}, forceBackfill={}",
                tenantId, tableName, lastVersion, forceBackfill);
        return ApiResult.success(cloudSyncReceiveService.pollDownQueue(
                tenantId, tableName, lastVersion, forceBackfill));
    }

    /**
     * 确认下发数据已消费
     */
    @PostMapping("/sync/poll/ack")
    public SyncResponse ackPoll(
            @RequestHeader(value = CloudIntegrationConstants.HEADER_API_KEY, required = false) String apiKey,
            @RequestHeader(value = CloudIntegrationConstants.HEADER_TENANT_ID, required = false) String tenantIdHeader,
            @RequestBody List<Long> queueIds) {

        Integer tenantId = parseTenantId(tenantIdHeader);
        if (tenantId != null && !cloudAuthService.validateToken(apiKey, tenantId)) {
            return SyncResponse.builder().success(false).message("认证失败").build();
        }
        cloudSyncReceiveService.ackDownQueue(queueIds);
        return SyncResponse.builder().success(true).message("确认成功").build();
    }

    private Integer parseTenantId(String tenantIdHeader) {
        if (!StringUtils.hasText(tenantIdHeader)) {
            return null;
        }
        try {
            return Integer.valueOf(tenantIdHeader.trim());
        } catch (NumberFormatException ex) {
            return null;
        }
    }
}
