import { getContainer } from '@bytelyst/cosmos';
import { config } from '../config/index.js';
import logger from '../utils/logger.js';

const CONTAINER_NAME = 'runtime_locks';

type LockScope = 'entry' | 'reconciliation';

interface RuntimeLockDocument {
    id: string;
    productId: string;
    scope: LockScope;
    profileId: string;
    symbol?: string;
    owner: string;
    expiresAt: number;
    updatedAt: string;
    ttl: number;
}

function isCosmosConfigured(): boolean {
    return Boolean(config.COSMOS_ENDPOINT && config.COSMOS_KEY);
}

function sanitizeLockToken(value: string): string {
    return String(value || '')
        .trim()
        .replace(/[^A-Za-z0-9._-]+/g, '_')
        .replace(/^_+|_+$/g, '') || 'global';
}

function buildEntryLockId(profileId: string, symbol?: string): string {
    return `entry:${sanitizeLockToken(profileId)}:${sanitizeLockToken(String(symbol || '').trim())}`;
}

function buildReconciliationLockId(profileId: string): string {
    return `reconciliation:${sanitizeLockToken(profileId)}`;
}

async function readLock(id: string): Promise<RuntimeLockDocument | null> {
    const container = getContainer(CONTAINER_NAME);
    try {
        const { resource } = await container.item(id, config.PRODUCT_ID).read<RuntimeLockDocument>();
        return resource || null;
    } catch (error) {
        const code = (error as { code?: number })?.code;
        if (code === 404) return null;
        throw error;
    }
}

async function writeLock(doc: RuntimeLockDocument): Promise<boolean> {
    const container = getContainer(CONTAINER_NAME);
    await container.items.upsert(doc);
    return true;
}

async function deleteLock(id: string): Promise<boolean> {
    const container = getContainer(CONTAINER_NAME);
    try {
        await container.item(id, config.PRODUCT_ID).delete();
        return true;
    } catch (error) {
        const code = (error as { code?: number })?.code;
        if (code === 404) return false;
        throw error;
    }
}

function isActive(doc: RuntimeLockDocument | null | undefined): boolean {
    return Boolean(doc && Number(doc.expiresAt) > Date.now());
}

export async function tryAcquireEntryLock(
    profileId: string,
    symbol: string | undefined,
    owner: string,
    ttlSeconds: number
): Promise<boolean> {
    if (!profileId || !owner) return false;
    if (!isCosmosConfigured()) return false;

    try {
        const id = buildEntryLockId(profileId, symbol);
        const existing = await readLock(id);
        if (isActive(existing) && existing?.owner !== owner) {
            return false;
        }

        await writeLock({
            id,
            productId: config.PRODUCT_ID,
            scope: 'entry',
            profileId,
            symbol: String(symbol || '').trim() || undefined,
            owner,
            expiresAt: Date.now() + Math.max(1, ttlSeconds) * 1000,
            updatedAt: new Date().toISOString(),
            ttl: Math.max(1, ttlSeconds)
        });
        return true;
    } catch (error) {
        logger.warn(`[DistributedLockRepo] Cosmos entry-lock acquire failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        return false;
    }
}

export async function releaseEntryLock(
    profileId: string,
    symbol: string | undefined,
    owner: string
): Promise<boolean> {
    if (!profileId || !owner) return false;
    if (!isCosmosConfigured()) return false;

    try {
        const id = buildEntryLockId(profileId, symbol);
        const existing = await readLock(id);
        if (!existing) return false;
        if (existing.owner !== owner) return false;
        return await deleteLock(id);
    } catch (error) {
        logger.warn(`[DistributedLockRepo] Cosmos entry-lock release failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        return false;
    }
}

export async function tryAcquireReconciliationLock(
    profileId: string,
    owner: string,
    ttlSeconds: number
): Promise<boolean> {
    if (!profileId || !owner) return false;
    if (!isCosmosConfigured()) return false;

    try {
        const id = buildReconciliationLockId(profileId);
        const existing = await readLock(id);
        if (isActive(existing) && existing?.owner !== owner) {
            return false;
        }

        await writeLock({
            id,
            productId: config.PRODUCT_ID,
            scope: 'reconciliation',
            profileId,
            owner,
            expiresAt: Date.now() + Math.max(1, ttlSeconds) * 1000,
            updatedAt: new Date().toISOString(),
            ttl: Math.max(1, ttlSeconds)
        });
        return true;
    } catch (error) {
        logger.warn(`[DistributedLockRepo] Cosmos reconciliation-lock acquire failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        return false;
    }
}

export async function releaseReconciliationLock(
    profileId: string,
    owner: string
): Promise<boolean> {
    if (!profileId || !owner) return false;
    if (!isCosmosConfigured()) return false;

    try {
        const id = buildReconciliationLockId(profileId);
        const existing = await readLock(id);
        if (!existing) return false;
        if (existing.owner !== owner) return false;
        return await deleteLock(id);
    } catch (error) {
        logger.warn(`[DistributedLockRepo] Cosmos reconciliation-lock release failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        return false;
    }
}

export async function isEntryLockActive(
    profileId: string,
    symbol: string | undefined
): Promise<boolean> {
    if (!profileId) return false;
    if (!isCosmosConfigured()) return false;

    try {
        const existing = await readLock(buildEntryLockId(profileId, symbol));
        return isActive(existing);
    } catch (error) {
        logger.warn(`[DistributedLockRepo] Cosmos entry-lock status failed: ${error instanceof Error ? error.message : 'unknown error'}`);
        return true;
    }
}
