package com.sino.mci.admin.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sino.mci.admin.dto.TestWebhookRequest;
import com.sino.mci.admin.dto.TestWebhookResponse;
import com.sino.mci.admin.dto.TenantWebhookResponse;
import com.sino.mci.admin.dto.UpdateTenantWebhookRequest;
import com.sino.mci.admin.entity.Tenant;
import com.sino.mci.admin.repository.TenantMapper;
import com.sino.mci.exception.BusinessException;
import com.sino.mci.inbound.webhook.WebhookSignature;
import com.sino.mci.inbound.webhook.WebhookSignatureService;
import com.sino.mci.shared.util.JsonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class TenantService {

    private static final String AUTH_CONFIG_WEBHOOK_SECRET = "webhook_secret";
    private static final String AUTH_CONFIG_SIGN_ALGORITHM = "sign_algorithm";
    private static final String DEFAULT_ALGORITHM = "hmac-sha256";

    private final TenantMapper tenantMapper;
    private final RestTemplate restTemplate;
    private final WebhookSignatureService signatureService;

    public TenantWebhookResponse getWebhookConfig(String tenantCode) {
        Tenant tenant = getTenant(tenantCode);
        TenantWebhookResponse response = new TenantWebhookResponse();
        response.setInboundWebhookUrl(tenant.getInboundWebhookUrl() != null ? tenant.getInboundWebhookUrl() : "");
        response.setAuthConfig(parseAuthConfig(tenant.getAuthConfig()));
        return response;
    }

    @Transactional
    public TenantWebhookResponse updateWebhookConfig(String tenantCode, UpdateTenantWebhookRequest request) {
        Tenant tenant = getTenant(tenantCode);
        tenant.setInboundWebhookUrl(request.getInboundWebhookUrl());
        tenant.setAuthConfig(JsonUtils.toJson(request.getAuthConfig()));
        tenantMapper.updateById(tenant);
        return getWebhookConfig(tenantCode);
    }

    public TestWebhookResponse testWebhook(String tenantCode, TestWebhookRequest request) {
        Tenant tenant = getTenant(tenantCode);
        Map<String, Object> authConfig = parseAuthConfig(tenant.getAuthConfig());
        String secret = getString(authConfig, AUTH_CONFIG_WEBHOOK_SECRET);
        if (!StringUtils.hasText(secret)) {
            return new TestWebhookResponse(false, "未配置 webhook_secret，无法签名测试请求");
        }
        String algorithm = getString(authConfig, AUTH_CONFIG_SIGN_ALGORITHM);
        if (!StringUtils.hasText(algorithm)) {
            algorithm = DEFAULT_ALGORITHM;
        }

        String payloadJson = JsonUtils.toJson(buildSamplePayload(tenantCode));
        WebhookSignature signature = signatureService.sign(tenantCode, payloadJson, secret, algorithm);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("X-Msg-Platform-Signature", signature.signature());
        headers.set("X-Msg-Platform-Timestamp", String.valueOf(signature.timestamp()));
        headers.set("X-Msg-Platform-Tenant", tenantCode);

        HttpEntity<String> entity = new HttpEntity<>(payloadJson, headers);
        try {
            ResponseEntity<String> response = restTemplate.exchange(
                    request.getUrl(), HttpMethod.POST, entity, String.class);
            if (response.getStatusCode().is2xxSuccessful()) {
                return new TestWebhookResponse(true, "测试推送成功，HTTP " + response.getStatusCode());
            }
            return new TestWebhookResponse(false, "测试推送失败，HTTP " + response.getStatusCode());
        } catch (RestClientException e) {
            log.warn("Webhook test failed for tenant {} to {}", tenantCode, request.getUrl(), e);
            return new TestWebhookResponse(false, "测试推送失败: " + e.getMessage());
        }
    }

    private Tenant getTenant(String tenantCode) {
        Tenant tenant = tenantMapper.selectOne(
                new LambdaQueryWrapper<Tenant>().eq(Tenant::getTenantCode, tenantCode));
        if (tenant == null) {
            throw new BusinessException("租户不存在: " + tenantCode);
        }
        return tenant;
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> parseAuthConfig(String authConfigJson) {
        if (authConfigJson == null || authConfigJson.isBlank()) {
            return new LinkedHashMap<>();
        }
        Map<String, Object> config = JsonUtils.fromJson(authConfigJson, Map.class);
        return config != null ? config : new LinkedHashMap<>();
    }

    private String getString(Map<String, Object> config, String key) {
        Object value = config.get(key);
        return value != null ? value.toString() : null;
    }

    private Map<String, Object> buildSamplePayload(String tenantCode) {
        Map<String, Object> payload = new LinkedHashMap<>();
        payload.put("event_id", "test_evt_001");
        payload.put("tenant_code", tenantCode);
        payload.put("channel_type", "wecom");
        payload.put("direction", "in");
        payload.put("event_type", "message");
        payload.put("content", Map.of("text", "这是一条 webhook 测试消息"));
        payload.put("timestamp", System.currentTimeMillis() / 1000);
        return payload;
    }
}
