import { apiRequest } from "@/shared/api/request";
import { API_ENDPOINTS, API_OPERATIONS, apiEndpointPath } from "@/shared/api/generated/endpoints";
import type {
    ApiPage,
    AppUserBanRecordDto,
    AppUserLoginLogDto,
    AppUserDto,
    AppUserPasswordPayload,
    AppUserUpdatePayload,
    AdminGrantPrettyDisplayIDResultDto,
    EntityId,
    GeneratePrettyDisplayIDsPayload,
    GrantPrettyDisplayIDPayload,
    PageQuery,
    PrettyDisplayIDDto,
    PrettyDisplayIDGenerationBatchDto,
    PrettyDisplayIDPoolDto,
    PrettyDisplayIDPoolPayload,
    SetPrettyDisplayIDStatusPayload,
} from "@/shared/api/types";

export async function listAppUsers(query: PageQuery = {}): Promise<ApiPage<AppUserDto>> {
    const endpoint = API_ENDPOINTS.appListUsers;
    const data = await apiRequest<ApiPage<RawAppUser> & { page_size?: number }>(
        apiEndpointPath(API_OPERATIONS.appListUsers),
        {
            method: endpoint.method,
            query,
        },
    );
    return normalizePage(data, normalizeAppUser);
}

export async function getAppUser(userId: EntityId): Promise<AppUserDto> {
    const endpoint = API_ENDPOINTS.appGetUser;
    const data = await apiRequest<RawAppUser>(apiEndpointPath(API_OPERATIONS.appGetUser, { id: userId }), {
        method: endpoint.method,
    });
    return normalizeAppUser(data);
}

export async function listAppUserLoginLogs(query: PageQuery = {}): Promise<ApiPage<AppUserLoginLogDto>> {
    const endpoint = API_ENDPOINTS.appListLoginLogs;
    const data = await apiRequest<ApiPage<RawAppUserLoginLog> & { page_size?: number }>(
        apiEndpointPath(API_OPERATIONS.appListLoginLogs),
        {
            method: endpoint.method,
            query,
        },
    );
    return normalizePage(data, normalizeAppUserLoginLog);
}

export async function listAppUserBans(query: PageQuery = {}): Promise<ApiPage<AppUserBanRecordDto>> {
    const endpoint = API_ENDPOINTS.appListBannedUsers;
    const data = await apiRequest<ApiPage<RawAppUserBanRecord> & { page_size?: number }>(
        apiEndpointPath(API_OPERATIONS.appListBannedUsers),
        {
            method: endpoint.method,
            query,
        },
    );
    return normalizePage(data, normalizeAppUserBanRecord);
}

export async function updateAppUser(userId: EntityId, payload: AppUserUpdatePayload): Promise<AppUserDto> {
    const endpoint = API_ENDPOINTS.appUpdateUser;
    const data = await apiRequest<RawAppUser, AppUserUpdatePayload>(
        apiEndpointPath(API_OPERATIONS.appUpdateUser, { id: userId }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
    return normalizeAppUser(data);
}

export async function banAppUser(userId: EntityId): Promise<AppUserDto> {
    const endpoint = API_ENDPOINTS.appBanUser;
    const data = await apiRequest<RawAppUser>(apiEndpointPath(API_OPERATIONS.appBanUser, { id: userId }), {
        method: endpoint.method,
    });
    return normalizeAppUser(data);
}

export async function unbanAppUser(userId: EntityId): Promise<AppUserDto> {
    const endpoint = API_ENDPOINTS.appUnbanUser;
    const data = await apiRequest<RawAppUser>(apiEndpointPath(API_OPERATIONS.appUnbanUser, { id: userId }), {
        method: endpoint.method,
    });
    return normalizeAppUser(data);
}

export function setAppUserPassword(
    userId: EntityId,
    payload: AppUserPasswordPayload,
): Promise<{ passwordSet: boolean }> {
    const endpoint = API_ENDPOINTS.appSetPassword;
    return apiRequest<{ passwordSet: boolean }, AppUserPasswordPayload>(
        apiEndpointPath(API_OPERATIONS.appSetPassword, { id: userId }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
}

// 靓号管理接口路径全部来自生成的 OpenAPI 端点，页面层只依赖这些函数，避免手写 URL 和契约漂移。
export async function listPrettyDisplayIDPools(query: PageQuery = {}): Promise<ApiPage<PrettyDisplayIDPoolDto>> {
    const endpoint = API_ENDPOINTS.listPrettyIdPools;
    const data = await apiRequest<ApiPage<RawPrettyDisplayIDPool>>(apiEndpointPath(API_OPERATIONS.listPrettyIdPools), {
        method: endpoint.method,
        query,
    });
    return normalizePage(data, normalizePrettyDisplayIDPool);
}

export async function createPrettyDisplayIDPool(payload: PrettyDisplayIDPoolPayload): Promise<PrettyDisplayIDPoolDto> {
    const endpoint = API_ENDPOINTS.createPrettyIdPool;
    const data = await apiRequest<RawPrettyDisplayIDPool, PrettyDisplayIDPoolPayload>(
        apiEndpointPath(API_OPERATIONS.createPrettyIdPool),
        {
            body: payload,
            method: endpoint.method,
        },
    );
    return normalizePrettyDisplayIDPool(data);
}

export async function updatePrettyDisplayIDPool(
    poolId: EntityId,
    payload: PrettyDisplayIDPoolPayload,
): Promise<PrettyDisplayIDPoolDto> {
    const endpoint = API_ENDPOINTS.updatePrettyIdPool;
    const data = await apiRequest<RawPrettyDisplayIDPool, PrettyDisplayIDPoolPayload>(
        apiEndpointPath(API_OPERATIONS.updatePrettyIdPool, { pool_id: poolId }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
    return normalizePrettyDisplayIDPool(data);
}

export async function generatePrettyDisplayIDs(
    poolId: EntityId,
    payload: GeneratePrettyDisplayIDsPayload,
): Promise<PrettyDisplayIDGenerationBatchDto> {
    const endpoint = API_ENDPOINTS.generatePrettyIds;
    const data = await apiRequest<RawPrettyDisplayIDGenerationBatch, GeneratePrettyDisplayIDsPayload>(
        apiEndpointPath(API_OPERATIONS.generatePrettyIds, { pool_id: poolId }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
    return normalizePrettyDisplayIDGenerationBatch(data);
}

export async function listPrettyDisplayIDs(query: PageQuery = {}): Promise<ApiPage<PrettyDisplayIDDto>> {
    const endpoint = API_ENDPOINTS.listPrettyIds;
    const data = await apiRequest<ApiPage<RawPrettyDisplayID>>(apiEndpointPath(API_OPERATIONS.listPrettyIds), {
        method: endpoint.method,
        query,
    });
    return normalizePage(data, normalizePrettyDisplayID);
}

export async function grantPrettyDisplayID(
    payload: GrantPrettyDisplayIDPayload,
): Promise<AdminGrantPrettyDisplayIDResultDto> {
    const endpoint = API_ENDPOINTS.grantPrettyId;
    const data = await apiRequest<RawAdminGrantPrettyDisplayIDResult, GrantPrettyDisplayIDPayload>(
        apiEndpointPath(API_OPERATIONS.grantPrettyId),
        {
            body: payload,
            method: endpoint.method,
        },
    );
    return normalizeAdminGrantPrettyDisplayIDResult(data);
}

export async function setPrettyDisplayIDStatus(
    prettyId: EntityId,
    payload: SetPrettyDisplayIDStatusPayload,
): Promise<PrettyDisplayIDDto> {
    const endpoint = API_ENDPOINTS.setPrettyIdStatus;
    const data = await apiRequest<RawPrettyDisplayID, SetPrettyDisplayIDStatusPayload>(
        apiEndpointPath(API_OPERATIONS.setPrettyIdStatus, { pretty_id: prettyId }),
        {
            body: payload,
            method: endpoint.method,
        },
    );
    return normalizePrettyDisplayID(data);
}

// 用户相关接口历史上既返回过 snake_case，也返回过 camelCase；在 API 边界归一化后，共享用户组件只消费稳定字段。
interface RawAppUser {
    avatar?: string;
    coin?: number;
    country?: string;
    country_display_name?: string;
    countryDisplayName?: string;
    country_name?: string;
    countryName?: string;
    created_at_ms?: number;
    createdAtMs?: number;
    default_display_user_id?: string;
    defaultDisplayUserId?: string;
    diamond?: number;
    display_user_id?: string;
    displayUserId?: string;
    gender?: string;
    last_active_at_ms?: number;
    lastActiveAtMs?: number;
    pretty_display_user_id?: string;
    prettyDisplayUserId?: string;
    pretty_id?: string;
    prettyId?: string;
    region_id?: number;
    regionId?: number;
    region_name?: string;
    regionName?: string;
    status?: string;
    updated_at_ms?: number;
    updatedAtMs?: number;
    user_id?: EntityId;
    userId?: EntityId;
    username?: string;
}

type RawAppUserBrief = RawAppUser;

interface RawAppUserBanOperator extends RawAppUserBrief {
    account?: string;
    admin_id?: EntityId;
    adminId?: EntityId;
    name?: string;
    type?: string;
}

interface RawAppUserBanRecord {
    created_at_ms?: number;
    createdAtMs?: number;
    id?: number;
    new_status?: string;
    newStatus?: string;
    old_status?: string;
    oldStatus?: string;
    operator?: RawAppUserBanOperator | null;
    reason?: string;
    request_id?: string;
    requestId?: string;
    target?: RawAppUserBrief;
}

interface RawAppUserLoginLog extends RawAppUserBrief {
    block_reason?: string;
    blockReason?: string;
    blocked?: boolean;
    channel?: string;
    country?: string;
    created_at_ms?: number;
    createdAtMs?: number;
    failure_code?: string;
    failureCode?: string;
    id?: number;
    ip_country_code?: string;
    ipCountryCode?: string;
    login_ip?: string;
    loginIp?: string;
    login_type?: string;
    loginType?: string;
    platform?: string;
    provider?: string;
    region_id?: number;
    regionId?: number;
    region_name?: string;
    regionName?: string;
    request_id?: string;
    requestId?: string;
    result?: string;
    risk_highlighted?: boolean;
    riskHighlighted?: boolean;
}

// Go 后台当前按 snake_case JSON 返回，生成类型和页面代码使用 camelCase；Raw 类型同时接收两种形态，便于后续切换生成客户端。
interface RawPrettyDisplayIDPool {
    app_code?: string;
    appCode?: string;
    created_at_ms?: number;
    createdAtMs?: number;
    created_by_admin_id?: EntityId;
    createdByAdminId?: EntityId;
    level_track?: string;
    levelTrack?: string;
    max_level?: number;
    maxLevel?: number;
    min_level?: number;
    minLevel?: number;
    name?: string;
    pool_id?: string;
    poolId?: string;
    rule_config_json?: string;
    ruleConfigJson?: string;
    rule_type?: string;
    ruleType?: string;
    sort_order?: number;
    sortOrder?: number;
    status?: string;
    updated_at_ms?: number;
    updatedAtMs?: number;
    updated_by_admin_id?: EntityId;
    updatedByAdminId?: EntityId;
}

interface RawPrettyDisplayID {
    app_code?: string;
    appCode?: string;
    assigned_at_ms?: number;
    assignedAtMs?: number;
    assigned_lease_id?: string;
    assignedLeaseId?: string;
    assigned_user_id?: EntityId;
    assignedUserId?: EntityId;
    created_at_ms?: number;
    createdAtMs?: number;
    created_by_admin_id?: EntityId;
    createdByAdminId?: EntityId;
    display_user_id?: string;
    displayUserId?: string;
    generated_batch_id?: string;
    generatedBatchId?: string;
    pool?: RawPrettyDisplayIDPool | null;
    pool_id?: string;
    poolId?: string;
    pretty_id?: string;
    prettyId?: string;
    release_reason?: string;
    releaseReason?: string;
    released_at_ms?: number;
    releasedAtMs?: number;
    source?: string;
    status?: string;
    updated_at_ms?: number;
    updatedAtMs?: number;
}

interface RawPrettyDisplayIDGenerationBatch {
    app_code?: string;
    appCode?: string;
    batch_id?: string;
    batchId?: string;
    created_at_ms?: number;
    createdAtMs?: number;
    generated_count?: number;
    generatedCount?: number;
    operator_admin_id?: EntityId;
    operatorAdminId?: EntityId;
    pool_id?: string;
    poolId?: string;
    request_id?: string;
    requestId?: string;
    requested_count?: number;
    requestedCount?: number;
    rule_config_json?: string;
    ruleConfigJson?: string;
    rule_type?: string;
    ruleType?: string;
    skipped_conflict_count?: number;
    skippedConflictCount?: number;
    status?: string;
    updated_at_ms?: number;
    updatedAtMs?: number;
}

interface RawAdminGrantPrettyDisplayIDResult {
    identity?: {
        default_display_user_id?: string;
        defaultDisplayUserId?: string;
        display_user_id?: string;
        displayUserId?: string;
        pretty_display_user_id?: string;
        prettyDisplayUserId?: string;
        pretty_id?: string;
        prettyId?: string;
        user_id?: EntityId;
        userId?: EntityId;
    };
    lease_id?: string;
    leaseId?: string;
    pretty_id?: string;
    prettyId?: string;
}

// 分页结构也做一次兼容，page_size 来自 Go 响应，pageSize 来自前端 ApiPage 约定。
function normalizePage<TRaw, TItem>(
    data: ApiPage<TRaw> & { page_size?: number },
    normalize: (item: TRaw) => TItem,
): ApiPage<TItem> {
    return {
        items: (data.items || []).map(normalize),
        page: Number(data.page || 1),
        pageSize: Number(data.pageSize || data.page_size || 20),
        total: Number(data.total || 0),
    };
}

function normalizeAppUser(item: RawAppUser = {}): AppUserDto {
    return {
        avatar: stringValue(item.avatar),
        coin: numberValue(item.coin),
        country: stringValue(item.country),
        countryDisplayName: stringValue(item.countryDisplayName ?? item.country_display_name),
        countryName: stringValue(item.countryName ?? item.country_name),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        defaultDisplayUserId: stringValue(item.defaultDisplayUserId ?? item.default_display_user_id),
        diamond: numberValue(item.diamond),
        displayUserId: stringValue(item.displayUserId ?? item.display_user_id),
        gender: stringValue(item.gender),
        lastActiveAtMs: numberValue(item.lastActiveAtMs ?? item.last_active_at_ms),
        prettyDisplayUserId: stringValue(item.prettyDisplayUserId ?? item.pretty_display_user_id),
        prettyId: stringValue(item.prettyId ?? item.pretty_id),
        regionId: numberValue(item.regionId ?? item.region_id),
        regionName: stringValue(item.regionName ?? item.region_name),
        status: stringValue(item.status),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
        userId: stringValue(item.userId ?? item.user_id),
        username: stringValue(item.username),
    };
}

function normalizeAppUserBrief(item: RawAppUserBrief = {}) {
    const user = normalizeAppUser(item);
    return {
        avatar: user.avatar,
        defaultDisplayUserId: user.defaultDisplayUserId,
        displayUserId: user.displayUserId,
        prettyDisplayUserId: user.prettyDisplayUserId,
        prettyId: user.prettyId,
        userId: user.userId,
        username: user.username,
    };
}

function normalizeAppUserBanOperator(item?: RawAppUserBanOperator | null) {
    if (!item) {
        return undefined;
    }
    const user = normalizeAppUserBrief(item);
    return {
        ...user,
        account: stringValue(item.account),
        adminId: stringValue(item.adminId ?? item.admin_id),
        name: stringValue(item.name),
        type: stringValue(item.type || "system"),
    };
}

function normalizeAppUserBanRecord(item: RawAppUserBanRecord = {}): AppUserBanRecordDto {
    return {
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        id: numberValue(item.id),
        newStatus: stringValue(item.newStatus ?? item.new_status),
        oldStatus: stringValue(item.oldStatus ?? item.old_status),
        operator: normalizeAppUserBanOperator(item.operator),
        reason: stringValue(item.reason),
        requestId: stringValue(item.requestId ?? item.request_id),
        target: normalizeAppUserBrief(item.target || {}),
    };
}

function normalizeAppUserLoginLog(item: RawAppUserLoginLog = {}): AppUserLoginLogDto {
    const user = normalizeAppUserBrief(item);
    return {
        ...user,
        blockReason: stringValue(item.blockReason ?? item.block_reason),
        blocked: Boolean(item.blocked),
        channel: stringValue(item.channel),
        country: stringValue(item.country),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        failureCode: stringValue(item.failureCode ?? item.failure_code),
        id: numberValue(item.id),
        ipCountryCode: stringValue(item.ipCountryCode ?? item.ip_country_code),
        loginIp: stringValue(item.loginIp ?? item.login_ip),
        loginType: stringValue(item.loginType ?? item.login_type),
        platform: stringValue(item.platform),
        provider: stringValue(item.provider),
        regionId: numberValue(item.regionId ?? item.region_id),
        regionName: stringValue(item.regionName ?? item.region_name),
        requestId: stringValue(item.requestId ?? item.request_id),
        result: stringValue(item.result),
        riskHighlighted: Boolean(item.riskHighlighted ?? item.risk_highlighted),
    };
}

// 池 DTO 在这里完成字段名和数值兜底，页面表格不再关心后端是否省略可选字段。
function normalizePrettyDisplayIDPool(item: RawPrettyDisplayIDPool): PrettyDisplayIDPoolDto {
    return {
        appCode: item.appCode ?? item.app_code ?? "",
        createdAtMs: item.createdAtMs ?? item.created_at_ms ?? 0,
        createdByAdminId: item.createdByAdminId ?? item.created_by_admin_id ?? "",
        levelTrack: item.levelTrack ?? item.level_track ?? "",
        maxLevel: Number(item.maxLevel ?? item.max_level ?? 0),
        minLevel: Number(item.minLevel ?? item.min_level ?? 0),
        name: item.name ?? "",
        poolId: item.poolId ?? item.pool_id ?? "",
        ruleConfigJson: item.ruleConfigJson ?? item.rule_config_json ?? "",
        ruleType: item.ruleType ?? item.rule_type ?? "",
        sortOrder: Number(item.sortOrder ?? item.sort_order ?? 0),
        status: item.status ?? "",
        updatedAtMs: item.updatedAtMs ?? item.updated_at_ms ?? 0,
        updatedByAdminId: item.updatedByAdminId ?? item.updated_by_admin_id ?? "",
    };
}

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

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

// 靓号明细包含池号和后台发放两类来源，pool 可能为空，归一化后页面只判断 source/status 即可。
function normalizePrettyDisplayID(item: RawPrettyDisplayID): PrettyDisplayIDDto {
    return {
        appCode: item.appCode ?? item.app_code ?? "",
        assignedAtMs: item.assignedAtMs ?? item.assigned_at_ms ?? 0,
        assignedLeaseId: item.assignedLeaseId ?? item.assigned_lease_id ?? "",
        assignedUserId: item.assignedUserId ?? item.assigned_user_id ?? "",
        createdAtMs: item.createdAtMs ?? item.created_at_ms ?? 0,
        createdByAdminId: item.createdByAdminId ?? item.created_by_admin_id ?? "",
        displayUserId: item.displayUserId ?? item.display_user_id ?? "",
        generatedBatchId: item.generatedBatchId ?? item.generated_batch_id ?? "",
        pool: item.pool ? normalizePrettyDisplayIDPool(item.pool) : null,
        poolId: item.poolId ?? item.pool_id ?? "",
        prettyId: item.prettyId ?? item.pretty_id ?? "",
        releaseReason: item.releaseReason ?? item.release_reason ?? "",
        releasedAtMs: item.releasedAtMs ?? item.released_at_ms ?? 0,
        source: item.source ?? "",
        status: item.status ?? "",
        updatedAtMs: item.updatedAtMs ?? item.updated_at_ms ?? 0,
    };
}

// 生成结果用于展示本次批量生成的真实落库数量和冲突跳过数量，数值统一转换，避免字符串数字影响统计。
function normalizePrettyDisplayIDGenerationBatch(
    item: RawPrettyDisplayIDGenerationBatch,
): PrettyDisplayIDGenerationBatchDto {
    return {
        appCode: item.appCode ?? item.app_code ?? "",
        batchId: item.batchId ?? item.batch_id ?? "",
        createdAtMs: item.createdAtMs ?? item.created_at_ms ?? 0,
        generatedCount: Number(item.generatedCount ?? item.generated_count ?? 0),
        operatorAdminId: item.operatorAdminId ?? item.operator_admin_id ?? "",
        poolId: item.poolId ?? item.pool_id ?? "",
        requestId: item.requestId ?? item.request_id ?? "",
        requestedCount: Number(item.requestedCount ?? item.requested_count ?? 0),
        ruleConfigJson: item.ruleConfigJson ?? item.rule_config_json ?? "",
        ruleType: item.ruleType ?? item.rule_type ?? "",
        skippedConflictCount: Number(item.skippedConflictCount ?? item.skipped_conflict_count ?? 0),
        status: item.status ?? "",
        updatedAtMs: item.updatedAtMs ?? item.updated_at_ms ?? 0,
    };
}

// 后台发放返回的是新 lease 和用户当前身份快照，identity 归一化后能直接用于测试和后续结果提示。
function normalizeAdminGrantPrettyDisplayIDResult(
    item: RawAdminGrantPrettyDisplayIDResult,
): AdminGrantPrettyDisplayIDResultDto {
    const identity = item.identity || {};
    return {
        identity: {
            defaultDisplayUserId: identity.defaultDisplayUserId ?? identity.default_display_user_id ?? "",
            displayUserId: identity.displayUserId ?? identity.display_user_id ?? "",
            prettyDisplayUserId: identity.prettyDisplayUserId ?? identity.pretty_display_user_id ?? "",
            prettyId: identity.prettyId ?? identity.pretty_id ?? "",
            userId: String(identity.userId ?? identity.user_id ?? ""),
        },
        leaseId: item.leaseId ?? item.lease_id ?? "",
        prettyId: item.prettyId ?? item.pretty_id ?? "",
    };
}
