package com.malk.apigw.caller;

import com.alibaba.fastjson.JSON;
import com.malk.server.aliwork.YDAuth;
import com.malk.server.aliwork.YDConf;
import com.malk.service.aliwork.YDClient_Form;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 调用方注册表
 *
 * <p>启动全量 + 定时刷新。数据源为宜搭权限表单（formUuid 配置 {@code com.caller.registry.formUuid}）。</p>
 */
@Slf4j
@Service
public class CallerRegistryService {

    @Autowired
    private CallerRegistryProperties props;

    @Autowired
    private YDConf selfConf;

    @Autowired
    private YDClient_Form ydForm;

    private final Map<String, CallerProfile> registry = new ConcurrentHashMap<>();

    @PostConstruct
    public void init() {
        try {
            loadAll();
        } catch (Exception e) {
            log.error("[CallerRegistry] 启动加载失败", e);
        }
    }

    @Scheduled(fixedDelayString = "${com.caller.registry.ttlSeconds:300}000")
    public void refresh() {
        try {
            loadAll();
        } catch (Exception e) {
            log.warn("[CallerRegistry] 定时刷新失败，旧值继续可用", e);
        }
    }

    public synchronized void loadAll() {
        if (props.getCaller().getFormUuid() == null || props.getCaller().getFormUuid().isEmpty()) {
            log.warn("[CallerRegistry] com.caller.registry.formUuid 未配置，跳过加载");
            return;
        }
        YDAuth auth = YDAuth.ofGlobal(selfConf);
        Map<String, CallerProfile> snapshot = new HashMap<>();
        int page = 1;
        while (true) {
            Map<String, Object> r = ydForm.searchForm(auth, props.getCaller().getFormUuid(), "{}", page, 100, null);
            List<Map<String, Object>> data = listFrom(r, "data");
            if (data == null || data.isEmpty()) break;
            for (Map<String, Object> row : data) {
                Map<String, Object> formData = toFormData(row);
                CallerProfile p = parseRow(formData);
                if (p != null && p.isEnabled()) {
                    snapshot.put(p.getCallerId(), p);
                }
            }
            Number total = numberFrom(r, "totalCount");
            if (total == null || snapshot.size() >= total.intValue()) break;
            page++;
        }
        registry.clear();
        registry.putAll(snapshot);
        log.info("[CallerRegistry] 加载完成 callers={}", registry.size());
    }

    public CallerProfile get(String callerId) {
        return registry.get(callerId);
    }

    public int size() {
        return registry.size();
    }

    private CallerProfile parseRow(Map<String, Object> row) {
        CallerRegistryProperties.Field f = props.getCaller().getField();
        String enabled = stringFrom(row, f.getEnabled());
        if (!"on".equalsIgnoreCase(enabled)) return null;

        List<String> actions = parseActions(stringFrom(row, f.getAllowedActions()));
        Object rl = row.get(f.getRateLimit());
        int rate = rl instanceof Number ? ((Number) rl).intValue() : 10;

        Date expireAt = null;
        Object eo = row.get(f.getExpireAt());
        if (eo instanceof Number) {
            expireAt = new Date(((Number) eo).longValue());
        }

        return CallerProfile.builder()
                .callerId(stringFrom(row, f.getCallerId()))
                .callerSecret(stringFrom(row, f.getCallerSecret()))
                .callerName(stringFrom(row, f.getCallerName()))
                .allowedActions(actions == null ? Collections.emptyList() : actions)
                .rateLimit(rate)
                .expireAt(expireAt)
                .enabled(true)
                .build();
    }

    @SuppressWarnings("unchecked")
    private static List<String> parseActions(String json) {
        if (json == null || json.isEmpty()) return new ArrayList<>();
        try {
            return JSON.parseArray(json, String.class);
        } catch (Exception e) {
            return new ArrayList<>();
        }
    }

    @SuppressWarnings("unchecked")
    private static Map<String, Object> toFormData(Map<String, Object> row) {
        Object fd = row.get("formData");
        if (fd instanceof Map) return (Map<String, Object>) fd;
        return row;
    }

    @SuppressWarnings("unchecked")
    private static List<Map<String, Object>> listFrom(Map<String, Object> m, String key) {
        Object v = m.get(key);
        return v instanceof List ? (List<Map<String, Object>>) v : new ArrayList<>();
    }

    private static Number numberFrom(Map<String, Object> m, String key) {
        Object v = m.get(key);
        return v instanceof Number ? (Number) v : null;
    }

    private static String stringFrom(Map<String, Object> m, String key) {
        Object v = m.get(key);
        return v == null ? null : String.valueOf(v);
    }
}
