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

export interface PolicyTemplateDto {
    createdAtMs: number;
    description: string;
    name: string;
    ruleJson: Record<string, unknown>;
    status: string;
    templateCode: string;
    templateId: number;
    templateVersion: string;
    updatedAtMs: number;
    versionId: number;
}

export interface PolicyInstanceDto {
    appCode: string;
    createdAtMs: number;
    effectiveFromMs: number;
    effectiveToMs: number;
    instanceCode: string;
    instanceId: number;
    lastPublishedAtMs: number;
    publishError: string;
    publishStatus: string;
    regionScope: string;
    status: string;
    templateCode: string;
    templateVersion: string;
    updatedAtMs: number;
}

export interface PolicyPublishDto {
    appCode: string;
    instanceCode: string;
    instanceId: number;
    jobId: number;
    publishedAtMs: number;
    publishedRegionIds: number[];
    status: string;
    targetCount: number;
    templateCode: string;
    templateVersion: string;
}

export interface PolicyTemplatePayload {
    description: string;
    name: string;
    rule_json: Record<string, unknown>;
    status: string;
    template_code: string;
    template_version: string;
}

export interface PolicyInstancePayload {
    effective_from_ms: number;
    effective_to_ms: number;
    instance_code: string;
    region_scope: string;
    status: string;
    template_code: string;
    template_version: string;
}

export function listPolicyTemplates(query: PageQuery = {}): Promise<ApiPage<PolicyTemplateDto>> {
    const endpoint = API_ENDPOINTS.listPolicyTemplates;
    return apiRequest<ApiPage<RawPolicyTemplate>>(apiEndpointPath(API_OPERATIONS.listPolicyTemplates), {
        method: endpoint.method,
        query,
    }).then(normalizeTemplatePage);
}

export function savePolicyTemplate(payload: PolicyTemplatePayload): Promise<PolicyTemplateDto> {
    const endpoint = API_ENDPOINTS.savePolicyTemplate;
    return apiRequest<RawPolicyTemplate, PolicyTemplatePayload>(apiEndpointPath(API_OPERATIONS.savePolicyTemplate), {
        body: payload,
        method: endpoint.method,
    }).then(normalizeTemplate);
}

export function listPolicyInstances(query: PageQuery = {}): Promise<ApiPage<PolicyInstanceDto>> {
    const endpoint = API_ENDPOINTS.listPolicyInstances;
    return apiRequest<ApiPage<RawPolicyInstance>>(apiEndpointPath(API_OPERATIONS.listPolicyInstances), {
        method: endpoint.method,
        query,
    }).then(normalizeInstancePage);
}

export function createPolicyInstance(payload: PolicyInstancePayload): Promise<PolicyInstanceDto> {
    const endpoint = API_ENDPOINTS.createPolicyInstance;
    return apiRequest<RawPolicyInstance, PolicyInstancePayload>(apiEndpointPath(API_OPERATIONS.createPolicyInstance), {
        body: payload,
        method: endpoint.method,
    }).then(normalizeInstance);
}

export function publishPolicyInstance(instanceId: EntityId): Promise<PolicyPublishDto> {
    const endpoint = API_ENDPOINTS.publishPolicyInstance;
    return apiRequest<RawPolicyPublish>(apiEndpointPath(API_OPERATIONS.publishPolicyInstance, { instance_id: instanceId }), {
        method: endpoint.method,
    }).then(normalizePublish);
}

export function updatePolicyInstanceStatus(instanceId: EntityId, status: string): Promise<PolicyInstanceDto> {
    const endpoint = API_ENDPOINTS.updatePolicyInstanceStatus;
    return apiRequest<RawPolicyInstance, { status: string }>(
        apiEndpointPath(API_OPERATIONS.updatePolicyInstanceStatus, { instance_id: instanceId }),
        {
            body: { status },
            method: endpoint.method,
        },
    ).then(normalizeInstance);
}

type RawPolicyTemplate = PolicyTemplateDto & {
    created_at_ms?: number | string;
    rule_json?: unknown;
    template_code?: string;
    template_id?: number | string;
    template_version?: string;
    updated_at_ms?: number | string;
    version_id?: number | string;
} & Record<string, unknown>;

type RawPolicyInstance = PolicyInstanceDto & {
    app_code?: string;
    created_at_ms?: number | string;
    effective_from_ms?: number | string;
    effective_to_ms?: number | string;
    instance_code?: string;
    instance_id?: number | string;
    last_published_at_ms?: number | string;
    publish_error?: string;
    publish_status?: string;
    region_scope?: string;
    template_code?: string;
    template_version?: string;
    updated_at_ms?: number | string;
} & Record<string, unknown>;

type RawPolicyPublish = PolicyPublishDto & {
    app_code?: string;
    instance_code?: string;
    instance_id?: number | string;
    job_id?: number | string;
    published_at_ms?: number | string;
    published_region_ids?: Array<number | string>;
    target_count?: number | string;
    template_code?: string;
    template_version?: string;
} & Record<string, unknown>;

function normalizeTemplatePage(page: ApiPage<RawPolicyTemplate>): ApiPage<PolicyTemplateDto> {
    return {
        ...page,
        pageSize: numberValue(page.pageSize ?? (page as unknown as Record<string, unknown>).page_size),
        items: (page.items || []).map(normalizeTemplate),
    };
}

function normalizeInstancePage(page: ApiPage<RawPolicyInstance>): ApiPage<PolicyInstanceDto> {
    return {
        ...page,
        pageSize: numberValue(page.pageSize ?? (page as unknown as Record<string, unknown>).page_size),
        items: (page.items || []).map(normalizeInstance),
    };
}

function normalizeTemplate(item: RawPolicyTemplate): PolicyTemplateDto {
    return {
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        description: stringValue(item.description),
        name: stringValue(item.name),
        ruleJson: normalizeRuleJson(item.ruleJson ?? item.rule_json),
        status: stringValue(item.status || "active"),
        templateCode: stringValue(item.templateCode ?? item.template_code),
        templateId: numberValue(item.templateId ?? item.template_id),
        templateVersion: stringValue(item.templateVersion ?? item.template_version),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
        versionId: numberValue(item.versionId ?? item.version_id),
    };
}

function normalizeInstance(item: RawPolicyInstance): PolicyInstanceDto {
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        createdAtMs: numberValue(item.createdAtMs ?? item.created_at_ms),
        effectiveFromMs: numberValue(item.effectiveFromMs ?? item.effective_from_ms),
        effectiveToMs: numberValue(item.effectiveToMs ?? item.effective_to_ms),
        instanceCode: stringValue(item.instanceCode ?? item.instance_code),
        instanceId: numberValue(item.instanceId ?? item.instance_id),
        lastPublishedAtMs: numberValue(item.lastPublishedAtMs ?? item.last_published_at_ms),
        publishError: stringValue(item.publishError ?? item.publish_error),
        publishStatus: stringValue((item.publishStatus ?? item.publish_status) || "draft"),
        regionScope: stringValue((item.regionScope ?? item.region_scope) || "all_active_regions"),
        status: stringValue(item.status || "active"),
        templateCode: stringValue(item.templateCode ?? item.template_code),
        templateVersion: stringValue(item.templateVersion ?? item.template_version),
        updatedAtMs: numberValue(item.updatedAtMs ?? item.updated_at_ms),
    };
}

function normalizePublish(item: RawPolicyPublish): PolicyPublishDto {
    return {
        appCode: stringValue(item.appCode ?? item.app_code),
        instanceCode: stringValue(item.instanceCode ?? item.instance_code),
        instanceId: numberValue(item.instanceId ?? item.instance_id),
        jobId: numberValue(item.jobId ?? item.job_id),
        publishedAtMs: numberValue(item.publishedAtMs ?? item.published_at_ms),
        publishedRegionIds: (item.publishedRegionIds || item.published_region_ids || []).map(numberValue),
        status: stringValue(item.status),
        targetCount: numberValue(item.targetCount ?? item.target_count),
        templateCode: stringValue(item.templateCode ?? item.template_code),
        templateVersion: stringValue(item.templateVersion ?? item.template_version),
    };
}

function normalizeRuleJson(value: unknown): Record<string, unknown> {
    if (typeof value === "string") {
        try {
            const parsed = JSON.parse(value);
            return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
        } catch {
            return {};
        }
    }
    return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : {};
}

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

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