import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints";
import { apiRequest } from "@/shared/api/request";
import type { ApiList } from "@/shared/api/types";

export interface RegionBlockDto {
    blockId: number;
    keyword: string;
    countryCode: string;
    enabled: boolean;
    createdAtMs: number;
    updatedAtMs: number;
}

export interface IPWhitelistDto {
    whitelistId: number;
    ipAddress: string;
    enabled: boolean;
    createdAtMs: number;
    updatedAtMs: number;
}

export interface UserWhitelistDto {
    whitelistId: number;
    userId: string;
    displayUserId: string;
    enabled: boolean;
    createdAtMs: number;
    updatedAtMs: number;
}

export interface RegionBlockPayload {
    keywords: string[];
    whitelist_ips?: string[];
    whitelist_user_ids?: string[];
}

export interface AddRegionBlockWhitelistIPResult {
    added: boolean;
    config: RegionBlockConfigDto;
}

export interface RegionBlockConfigDto extends ApiList<RegionBlockDto> {
    whitelistItems: IPWhitelistDto[];
    whitelistTotal: number;
    whitelistUserItems: UserWhitelistDto[];
    whitelistUserTotal: number;
}

type RawRegionBlock = RegionBlockDto & Record<string, unknown>;
type RawIPWhitelist = IPWhitelistDto & Record<string, unknown>;
type RawUserWhitelist = UserWhitelistDto & Record<string, unknown>;
type RawRegionBlockConfig = ApiList<RawRegionBlock> & Record<string, unknown>;

export function listRegionBlocks(): Promise<RegionBlockConfigDto> {
    const endpoint = API_ENDPOINTS.listRegionBlocks;
    return apiRequest<RawRegionBlockConfig>(apiEndpointPath(API_OPERATIONS.listRegionBlocks), {
        method: endpoint.method,
    }).then(normalizeRegionBlockConfig);
}

export function replaceRegionBlocks(payload: RegionBlockPayload): Promise<RegionBlockConfigDto> {
    const endpoint = API_ENDPOINTS.replaceRegionBlocks;
    return apiRequest<RawRegionBlockConfig, RegionBlockPayload>(
        apiEndpointPath(API_OPERATIONS.replaceRegionBlocks),
        {
            body: payload,
            method: endpoint.method,
        },
    ).then(normalizeRegionBlockConfig);
}

export async function addRegionBlockWhitelistIP(ipAddress: string): Promise<AddRegionBlockWhitelistIPResult> {
    const current = await listRegionBlocks();
    const keywords = (current.items || []).map((item) => item.keyword).filter(Boolean);
    const whitelistIPs = (current.whitelistItems || []).map((item) => item.ipAddress).filter(Boolean);
    const normalizedIP = stringValue(ipAddress).trim();

    // 后端当前只提供整份配置替换接口；快捷追加前先读取最新配置并合并，避免把已保存的屏蔽词或其他 IP 覆盖掉。
    if (whitelistIPs.some((item) => normalizeKey(item) === normalizeKey(normalizedIP))) {
        return { added: false, config: current };
    }

    const config = await replaceRegionBlocks({
        keywords,
        whitelist_ips: [...whitelistIPs, normalizedIP],
    });
    return { added: true, config };
}

function normalizeRegionBlockConfig(data: RawRegionBlockConfig): RegionBlockConfigDto {
    const rawWhitelist = (data.whitelistItems ?? data.whitelist_items ?? []) as RawIPWhitelist[];
    const rawUserWhitelist = (data.whitelistUserItems ?? data.whitelist_user_items ?? []) as RawUserWhitelist[];
    return {
        items: (data.items || []).map(normalizeRegionBlock),
        total: Number(data.total || 0),
        whitelistItems: rawWhitelist.map(normalizeIPWhitelist),
        whitelistTotal: numberValue(data.whitelistTotal ?? data.whitelist_total),
        whitelistUserItems: rawUserWhitelist.map(normalizeUserWhitelist),
        whitelistUserTotal: numberValue(data.whitelistUserTotal ?? data.whitelist_user_total),
    };
}

function normalizeRegionBlock(item: RawRegionBlock): RegionBlockDto {
    return {
        blockId: numberValue(item.blockId ?? item.block_id),
        keyword: stringValue(item.keyword),
        countryCode: stringValue(item.countryCode ?? item.country_code),
        enabled: Boolean(item.enabled),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeIPWhitelist(item: RawIPWhitelist): IPWhitelistDto {
    return {
        whitelistId: numberValue(item.whitelistId ?? item.whitelist_id),
        ipAddress: stringValue(item.ipAddress ?? item.ip_address),
        enabled: Boolean(item.enabled),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizeUserWhitelist(item: RawUserWhitelist): UserWhitelistDto {
    return {
        whitelistId: numberValue(item.whitelistId ?? item.whitelist_id),
        userId: stringValue(item.userId ?? item.user_id),
        displayUserId: stringValue(item.displayUserId ?? item.display_user_id),
        enabled: Boolean(item.enabled),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function stringValue(value: unknown) {
    return value === undefined || value === null ? "" : String(value);
}

function normalizeKey(value: unknown) {
    return String(value || "").trim().toLowerCase();
}

function numberValue(value: unknown) {
    const number = Number(value || 0);
    return Number.isFinite(number) ? number : 0;
}
