"use client";

import { useEffect, useRef } from "react";
import { createClient } from "@/lib/supabase/client";
import { useCanvasStore } from "@/lib/store";
import type { DraggableElement, CanvasData } from "@/lib/types";

interface UseRealtimeCanvasOptions {
    teamIdOverride?: string | null;
}

/**
 * Hook to subscribe to real-time canvas updates from Supabase
 * When another user on the same team edits a canvas, changes are pushed live
 * 
 * @param canvasId - The canvas template ID to monitor
 * @param options - Configuration options including optional teamId override for admins
 */
export function useRealtimeCanvas(canvasId: string, options: UseRealtimeCanvasOptions = {}) {
    const { teamIdOverride } = options;
    const supabase = createClient();

    // Get store methods
    const getCanvas = useCanvasStore((state) => state.getCanvas);
    const mergeCanvasFields = useCanvasStore((state) => state.mergeCanvasFields);

    // Track last local update to prevent feedback loops
    const lastLocalUpdateRef = useRef<number>(0);
    const isUpdatingFromRealtimeRef = useRef<boolean>(false);

    // Subscribe to hasUnsavedChanges to track local updates
    const hasUnsavedChanges = useCanvasStore((state) => state.hasUnsavedChanges);

    // Update local timestamp when there are local changes
    useEffect(() => {
        if (hasUnsavedChanges && !isUpdatingFromRealtimeRef.current) {
            lastLocalUpdateRef.current = Date.now();
        }
    }, [hasUnsavedChanges]);

    useEffect(() => {
        // Determine effective teamId (admin override or from auth context)
        // We need to get teamId from auth context indirectly via the options
        const effectiveTeamId = teamIdOverride;

        if (!effectiveTeamId) {
            // Can't subscribe without a team ID - this will be handled by the
            // parent component which should pass teamId
            return;
        }

        console.log(`[Realtime] Setting up subscription for canvas: ${canvasId}, team: ${effectiveTeamId}`);

        // Create a unique channel for this team's canvas updates
        const channelName = `canvas-updates:${effectiveTeamId}`;

        const channel = supabase
            .channel(channelName)
            .on(
                'postgres_changes',
                {
                    event: '*', // Listen to INSERT, UPDATE, DELETE
                    schema: 'public',
                    table: 'canvas_data',
                    filter: `team_id=eq.${effectiveTeamId}`,
                },
                (payload) => {
                    console.log('[Realtime] Received change:', payload.eventType, payload);

                    // Extract the canvas_id from the payload
                    const record = payload.new as {
                        canvas_id?: string;
                        fields?: Record<string, string | string[] | null>;
                        elements?: DraggableElement[];
                        metadata?: CanvasData["metadata"];
                        updated_at?: string;
                    } | null;

                    const oldRecord = payload.old as { canvas_id?: string } | null;

                    // Get the canvas_id from the payload
                    const affectedCanvasId = record?.canvas_id || oldRecord?.canvas_id;

                    // Only process updates for the current canvas
                    if (affectedCanvasId !== canvasId) {
                        console.log(`[Realtime] Ignoring update for different canvas: ${affectedCanvasId}`);
                        return;
                    }

                    // Check if this was a local update that we just saved
                    // If the update happened within 3 seconds of our last local change, ignore it
                    // (accounts for debounce chain: 500ms field + 1000ms autosave + network)
                    const timeSinceLocalUpdate = Date.now() - lastLocalUpdateRef.current;
                    if (timeSinceLocalUpdate < 3000) {
                        console.log(`[Realtime] Ignoring update - likely our own save (${timeSinceLocalUpdate}ms ago)`);
                        return;
                    }

                    if (payload.eventType === 'INSERT' || payload.eventType === 'UPDATE') {
                        if (!record) return;

                        // Get current canvas data
                        const currentCanvas = getCanvas(canvasId);

                        // Merge remote data with local data
                        // If remote updated_at is newer, use remote data
                        const remoteUpdatedAt = record.updated_at
                            ? new Date(record.updated_at).getTime()
                            : 0;
                        const localUpdatedAt = currentCanvas?.updatedAt || 0;

                        // Only update if remote is newer
                        if (remoteUpdatedAt > localUpdatedAt) {
                            console.log(`[Realtime] Applying remote update with field-level merge (remote: ${remoteUpdatedAt}, local: ${localUpdatedAt})`);

                            // Mark that we're updating from realtime to prevent feedback loop
                            isUpdatingFromRealtimeRef.current = true;

                            // MERGE remote fields with local fields to preserve pending local edits
                            // Local fields take precedence so unsaved work isn't lost
                            mergeCanvasFields(
                                canvasId,
                                record.fields || {},
                                record.elements || [],
                                record.metadata || {},
                                remoteUpdatedAt,
                            );

                            // Reset the flag after a short delay
                            setTimeout(() => {
                                isUpdatingFromRealtimeRef.current = false;
                            }, 100);
                        } else {
                            console.log(`[Realtime] Ignoring older remote update`);
                        }
                    } else if (payload.eventType === 'DELETE') {
                        console.log(`[Realtime] Canvas ${canvasId} was deleted by another user`);
                        // Optionally handle deletion - for now just log
                    }
                }
            )
            .subscribe((status) => {
                console.log(`[Realtime] Subscription status for ${channelName}:`, status);
            });

        // Cleanup on unmount
        return () => {
            console.log(`[Realtime] Unsubscribing from ${channelName}`);
            supabase.removeChannel(channel);
        };
    }, [canvasId, teamIdOverride, supabase, getCanvas, mergeCanvasFields]);
}
