import { create } from "zustand";
import type { Week, Day, CanvasData, DraggableElement, FieldValue } from "./types";

interface CanvasStore {
  // Active state
  activeWeek: Week;
  activeCanvasId: string | null;

  // Canvas data (in-memory only, persisted to Supabase)
  canvasData: Record<string, CanvasData>;

  // UI state
  isEditing: boolean;
  hasUnsavedChanges: boolean;

  // Actions
  setActiveWeek: (week: Week) => void;
  setActiveCanvas: (canvasId: string | null) => void;

  // Canvas CRUD
  getCanvas: (canvasId: string) => CanvasData | undefined;
  updateCanvasField: (canvasId: string, fieldId: string, value: FieldValue) => void;
  updateCanvasMetadata: (canvasId: string, metadata: Partial<CanvasData["metadata"]>) => void;
  initializeCanvas: (canvasId: string, templateId: string, week: Week, day: Day, title: string) => void;
  resetCanvas: (canvasId: string, templateId: string, week: Week, day: Day, title: string) => void;

  // Real-time sync from external source
  setCanvasData: (canvasId: string, data: Partial<CanvasData>) => void;
  // Merge remote fields with local fields (for real-time updates)
  // Local fields take precedence to preserve pending unsaved edits
  mergeCanvasFields: (canvasId: string, remoteFields: Record<string, FieldValue>, remoteElements?: DraggableElement[], remoteMetadata?: CanvasData["metadata"], remoteUpdatedAt?: number) => void;

  // Draggable elements
  addElement: (canvasId: string, element: DraggableElement) => void;
  updateElementPosition: (canvasId: string, elementId: string, position: { x: number; y: number }) => void;
  updateElementLabel: (canvasId: string, elementId: string, label: string) => void;
  removeElement: (canvasId: string, elementId: string) => void;

  // Editing state
  setEditing: (isEditing: boolean) => void;
  markAsChanged: () => void;
  markAsSaved: () => void;

  // Reset store (for logout/team switch)
  resetStore: () => void;
}

const initialState = {
  activeWeek: 2 as Week,
  activeCanvasId: null,
  canvasData: {},
  isEditing: false,
  hasUnsavedChanges: false,
};

export const useCanvasStore = create<CanvasStore>()((set, get) => ({
  // Initial state
  ...initialState,

  // Week navigation
  setActiveWeek: (week) => set({ activeWeek: week }),
  setActiveCanvas: (canvasId) => set({ activeCanvasId: canvasId }),

  // Get canvas data
  getCanvas: (canvasId) => get().canvasData[canvasId],

  // Update canvas field
  updateCanvasField: (canvasId, fieldId, value) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas) return state;

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            fields: {
              ...canvas.fields,
              [fieldId]: value,
            },
            metadata: {
              ...canvas.metadata,
              status: 'started',
            },
            updatedAt: Date.now(),
          },
        },
        hasUnsavedChanges: true,
      };
    });
  },

  // Update canvas metadata
  updateCanvasMetadata: (canvasId, metadata) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas) return state;

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            metadata: { ...canvas.metadata, ...metadata },
            updatedAt: Date.now(),
          },
        },
      };
    });
  },

  // Initialize a new canvas from template
  initializeCanvas: (canvasId, templateId, week, day, title) => {
    set((state) => {
      if (state.canvasData[canvasId]) return state;

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            id: canvasId,
            templateId,
            week,
            day,
            title,
            fields: {},
            elements: [],
            metadata: {},
            createdAt: Date.now(),
            updatedAt: Date.now(),
          },
        },
      };
    });
  },

  // Set canvas data from external source (realtime updates)
  setCanvasData: (canvasId, data) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas) {
        // Canvas doesn't exist yet, create it with partial data
        return {
          canvasData: {
            ...state.canvasData,
            [canvasId]: {
              id: canvasId,
              templateId: canvasId,
              week: 2, // Default, will be overwritten
              day: 1,
              title: '',
              fields: {},
              elements: [],
              metadata: {},
              createdAt: Date.now(),
              updatedAt: Date.now(),
              ...data,
            } as CanvasData,
          },
        };
      }

      // Merge with existing canvas
      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            fields: data.fields ?? canvas.fields,
            elements: data.elements ?? canvas.elements,
            metadata: data.metadata ?? canvas.metadata,
            updatedAt: data.updatedAt ?? Date.now(),
          },
        },
        // Don't mark as unsaved - this came from the server
      };
    });
  },

  // Merge remote fields with local fields (for real-time updates)
  // Remote fields serve as the base; local fields override to preserve pending edits
  mergeCanvasFields: (canvasId, remoteFields, remoteElements, remoteMetadata, remoteUpdatedAt) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas) {
        // Canvas doesn't exist yet — just set the remote data
        return {
          canvasData: {
            ...state.canvasData,
            [canvasId]: {
              id: canvasId,
              templateId: canvasId,
              week: 2,
              day: 1,
              title: '',
              fields: remoteFields,
              elements: remoteElements || [],
              metadata: remoteMetadata || {},
              createdAt: Date.now(),
              updatedAt: remoteUpdatedAt || Date.now(),
            } as CanvasData,
          },
        };
      }

      // Merge: remote fields as base, local fields override
      // This preserves any field the local user has edited but not yet saved
      const mergedFields = { ...remoteFields, ...canvas.fields };

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            fields: mergedFields,
            elements: remoteElements ?? canvas.elements,
            metadata: remoteMetadata ?? canvas.metadata,
            updatedAt: remoteUpdatedAt ?? Date.now(),
          },
        },
        // Don't mark as unsaved — this came from the server
      };
    });
  },

  // Draggable elements
  addElement: (canvasId, element) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas) return state;

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            elements: [...(canvas.elements || []), element],
            metadata: {
              ...canvas.metadata,
              status: 'started',
            },
            updatedAt: Date.now(),
          },
        },
        hasUnsavedChanges: true,
      };
    });
  },

  updateElementPosition: (canvasId, elementId, position) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas?.elements) return state;

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            elements: canvas.elements.map((el) =>
              el.id === elementId ? { ...el, position } : el
            ),
            metadata: {
              ...canvas.metadata,
              status: 'started',
            },
            updatedAt: Date.now(),
          },
        },
        hasUnsavedChanges: true,
      };
    });
  },

  updateElementLabel: (canvasId, elementId, label) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas?.elements) return state;

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            elements: canvas.elements.map((el) =>
              el.id === elementId ? { ...el, label } : el
            ),
            metadata: {
              ...canvas.metadata,
              status: 'started',
            },
            updatedAt: Date.now(),
          },
        },
        hasUnsavedChanges: true,
      };
    });
  },

  removeElement: (canvasId, elementId) => {
    set((state) => {
      const canvas = state.canvasData[canvasId];
      if (!canvas?.elements) return state;

      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            ...canvas,
            elements: canvas.elements.filter((el) => el.id !== elementId),
            metadata: {
              ...canvas.metadata,
              status: 'started',
            },
            updatedAt: Date.now(),
          },
        },
        hasUnsavedChanges: true,
      };
    });
  },

  // Editing state management
  setEditing: (isEditing) => set({ isEditing }),
  markAsChanged: () => set({ hasUnsavedChanges: true }),
  markAsSaved: () => set({ hasUnsavedChanges: false }),

  // Reset store (useful when logging out or switching teams)
  resetStore: () => set(initialState),

  // Reset a specific canvas to its template state
  resetCanvas: (canvasId, templateId, week, day, title) => {
    set((state) => {
      return {
        canvasData: {
          ...state.canvasData,
          [canvasId]: {
            id: canvasId,
            templateId,
            week,
            day,
            title,
            fields: {},
            elements: [],
            metadata: {
              status: 'not_started',
            },
            createdAt: Date.now(),
            updatedAt: Date.now(),
          },
        },
        hasUnsavedChanges: true,
      };
    });
  },
}));
