// External imports
import {
    TLAssetStore,
    uniqueId,
    TLAsset,
    TLBookmarkAsset,
    AssetRecordType,
    getHashForString,
} from '@tldraw/tldraw';
import { logger } from '../../debugConfig';

export interface SyncConnectionOptions {
    userId: string;
    displayName: string;
    color: string;
    roomId?: string;
    baseUrl: string;
    /** Runtime-fetched TLSync auth token (from API, not baked into bundle). */
    token?: string;
}

/**
 * Fetch a short-lived TLSync auth token from the API backend.
 * The API holds the shared secret server-side and issues tokens
 * authenticated via the user's Supabase session.
 */
export async function fetchTlsyncToken(apiBase?: string): Promise<string> {
    const base = apiBase || import.meta.env.VITE_API_BASE || 'https://api.classroomcopilot.ai';
    try {
        const { supabase } = await import('../../supabaseClient');
        const { data: { session } } = await supabase.auth.getSession();
        if (!session?.access_token) {
            logger.warn('sync-service', 'No Supabase session for TLSync token fetch');
            return '';
        }
        const res = await fetch(`${base}/tlsync/token`, {
            headers: { Authorization: `Bearer ${session.access_token}` },
        });
        if (!res.ok) {
            logger.warn('sync-service', `TLSync token endpoint returned ${res.status}`);
            return '';
        }
        const { token } = await res.json();
        return token || '';
    } catch (err) {
        logger.warn('sync-service', 'Failed to fetch TLSync token from API', { err });
        return '';
    }
}

export function createSyncConnectionOptions(options: SyncConnectionOptions) {
    const {
        userId,
        displayName,
        roomId = 'multiplayer',
        baseUrl

    } = options;

    // Ensure we have valid user info
    if (!userId || !displayName) {
        logger.warn('sync-service', 'Missing user information', { userId, displayName });
    }

    // Create a unique room ID if not provided
    const effectiveRoomId = roomId || `room-${uniqueId()}`;

    const multiplayerAssets: TLAssetStore = {
        async upload(_asset: unknown, file: File) {
            const id = uniqueId();
            const objectName = `${id}-${file.name}`;
            const uploadPath = '/uploads';
            const url = `${baseUrl}${uploadPath}/${encodeURIComponent(objectName)}`;

            try {
                const response = await fetch(url, {
                    method: 'PUT',
                    body: file,
                    headers: {
                        'Content-Type': file.type
                    }
                });

                if (!response.ok) {
                    const errorDetail = await response.text();
                    throw new Error(`Failed to upload asset: ${response.statusText} - Details: ${errorDetail}`);
                }

                return url;
            } catch (error) {
                logger.error('sync-service', 'Error during asset upload: ', error);
                throw error;
            }
        },
        resolve(asset: TLAsset) {
            return asset.props.src ?? '';
        }
    };

    logger.info('sync-service', '🔄 Creating sync connection', {
        userId,
        displayName,
        roomId: effectiveRoomId
    });

    // Token is supplied at runtime via the API (not from build-time env)
    const token = options.token ?? '';
    const tokenParam = token ? `?token=${encodeURIComponent(token)}` : '';

    return {
        uri: `${baseUrl}/connect/${effectiveRoomId}${tokenParam}`,
        assets: multiplayerAssets,
        roomId: effectiveRoomId
    };
}

export async function handleExternalAsset(baseUrl: string, url: string): Promise<TLBookmarkAsset> {
    const asset: TLBookmarkAsset = {
        id: AssetRecordType.createId(getHashForString(url)),
        typeName: 'asset',
        type: 'bookmark',
        props: {
            src: url,
            description: '',
            image: '',
            favicon: '',
            title: ''
        },
        meta: {}
    };

    try {
        const response = await fetch(`${baseUrl}/unfurl?url=${encodeURIComponent(url)}`);
        const data = await response.json();

        asset.props = {
            ...asset.props,
            ...data
        };
    } catch (error) {
        logger.error('sync-service', 'Error unfurling URL:', error);
    }

    return asset;
}

export function generateSharedRoomId(path: string): string {
    // Create a deterministic room ID based on the path
    const sanitizedPath = path.replace(/[^a-zA-Z0-9]/g, '-');
    return `shared-${sanitizedPath}`;
}
