import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';

// Types
export interface Position {
    x: number;
    y: number;
}

export interface Size {
    width: number;
    height: number;
}

export interface LayoutPosition {
    id: string;
    sectionId: string;
    row: number;
    column: number;
    slot: number;
    status: 'EMPTY' | 'PLANTED' | 'HARVESTED' | 'ISSUE' | 'RESERVED';
    plantId?: string;
    plant?: {
        id: string;
        tagNumber: string;
        batchId?: string;
        address: string;
        status: string;
        batch?: {
            id: string;
            name: string;
            strain?: string;
            stage?: string;
            color?: string;
        };
        healthStatus?: 'HEALTHY' | 'STRESSED' | 'SICK' | 'DEAD';
    };
}

export interface LayoutSection {
    id: string;
    roomId: string;
    name: string;
    code: string;
    type: 'TABLE' | 'RACK' | 'TRAY' | 'HANGER' | 'FLOOR';
    position: Position; // Relative to room
    size: Size;
    rows: number;
    columns: number;
    tiers?: number;
    spacing: number; // inches between positions
    positions?: LayoutPosition[];
}

export interface LayoutRoom {
    id: string;
    name: string;
    code: string;
    type: 'VEG' | 'FLOWER' | 'CLONE' | 'DRY' | 'CURE' | 'TRIM' | 'VAULT' | 'OTHER';
    floorId: string;
    position: Position;
    size: Size;
    rotation: number;
    color?: string;
    // sections removed (normalized)
}

export interface LayoutFloor {
    id: string;
    buildingId?: string;
    name: string;
    number: number;
    width?: number;
    height?: number;
    size?: Size;
    rooms?: LayoutRoom[];
}

export interface LayoutBuilding {
    id: string;
    propertyId?: string;
    name: string;
    code: string;
    floors: LayoutFloor[];
}

export interface LayoutProperty {
    id: string;
    name: string;
    buildings: LayoutBuilding[];
}

export interface LayoutSnapshot {
    rooms: LayoutRoom[];
    sections: LayoutSection[];
}

// Room type colors
export const ROOM_COLORS: Record<LayoutRoom['type'], string> = {
    VEG: '#10b981',      // Emerald
    FLOWER: '#a855f7',   // Purple
    CLONE: '#3b82f6',    // Blue
    DRY: '#f59e0b',      // Amber
    CURE: '#f97316',     // Orange
    TRIM: '#64748b',     // Slate
    VAULT: '#71717a',    // Zinc
    OTHER: '#6b7280',    // Gray
};

interface LayoutState {
    // Current context
    propertyId: string | null;
    buildingId: string | null;
    floorId: string | null;

    // Data
    property: (LayoutProperty & { address?: string }) | null;
    rooms: LayoutRoom[];
    sections: LayoutSection[];

    // Canvas state
    zoom: number;
    pan: Position;
    showGrid: boolean;
    snapToGrid: boolean;
    gridSize: number; // feet

    // Selection
    selectedIds: string[];
    hoveredId: string | null;
    selectedPosition: (LayoutPosition & { sectionName?: string; roomName?: string }) | null;

    // Tool state
    activeTool: 'select' | 'pan' | 'room' | 'section';
    pendingRoomType: LayoutRoom['type'] | null;

    // History
    past: LayoutSnapshot[];
    future: LayoutSnapshot[];

    // Actions
    setProperty: (property: LayoutProperty & { address?: string }) => void;
    setBuilding: (buildingId: string) => void;
    setFloor: (floorId: string) => void;
    loadRooms: (rooms: LayoutRoom[]) => void;
    loadSections: (sections: LayoutSection[]) => void;
    clearRooms: () => void;

    // Canvas actions
    setZoom: (zoom: number) => void;
    setPan: (pan: Position) => void;
    zoomIn: () => void;
    zoomOut: () => void;
    resetView: () => void;
    toggleGrid: () => void;
    toggleSnap: () => void;

    // Selection
    select: (ids: string[]) => void;
    addToSelection: (id: string) => void;
    clearSelection: () => void;
    setHovered: (id: string | null) => void;
    setSelectedPosition: (position: (LayoutPosition & { sectionName?: string; roomName?: string }) | null) => void;

    // Room CRUD
    addRoom: (room: Omit<LayoutRoom, 'id' | 'sections'>) => string;
    updateRoom: (id: string, updates: Partial<LayoutRoom>) => void;
    deleteRoom: (id: string) => void;
    moveRoom: (id: string, position: Position) => void;
    resizeRoom: (id: string, size: Size) => void;

    // Section CRUD
    addSection: (section: Omit<LayoutSection, 'id'>) => string;
    updateSection: (id: string, updates: Partial<LayoutSection>) => void;
    deleteSection: (id: string) => void;

    // Tool
    setActiveTool: (tool: LayoutState['activeTool']) => void;
    setPendingRoomType: (type: LayoutRoom['type'] | null) => void;

    // History
    saveSnapshot: () => void;
    undo: () => void;
    redo: () => void;
    canUndo: () => boolean;
    canRedo: () => boolean;
}

const generateId = () => crypto.randomUUID();

export const useLayoutStore = create<LayoutState>()(
    immer((set, get) => ({
        // Initial state
        propertyId: null,
        buildingId: null,
        floorId: null,
        property: null,
        rooms: [],
        sections: [],
        zoom: 1,
        pan: { x: 0, y: 0 },
        showGrid: true,
        snapToGrid: true,
        gridSize: 1, // 1 foot
        selectedIds: [],
        hoveredId: null,
        selectedPosition: null,
        activeTool: 'select',
        pendingRoomType: null,
        past: [],
        future: [],

        // Property/Floor
        setProperty: (property) => set({ property, propertyId: property.id }),
        setBuilding: (buildingId) => set({ buildingId }),
        setFloor: (floorId) => set({ floorId }),
        loadRooms: (rooms) => set(state => {
            state.rooms = rooms.map(r => ({ ...r, sections: undefined })); // Ensure sections are removed from room object
            // Extract sections if they exist in the room (during initial full load)
            const sections: LayoutSection[] = [];
            rooms.forEach((r: any) => {
                if (r.sections) {
                    sections.push(...r.sections);
                }
            });
            // We replace sections on full room load? Or append?
            // Typically loadRooms implies "Load Floor", so we replace sections for this floor.
            // But extracting floorId from rooms is tricky if rooms is empty.
            // For simplicity, we just add them for now.
            // Actually loadRooms replaces state.rooms.
            // We should replace state.sections for these rooms.
            const roomIds = new Set(rooms.map(r => r.id));
            state.sections = state.sections.filter(s => !roomIds.has(s.roomId));
            state.sections.push(...sections);
            state.past = [];
            state.future = [];
        }),
        loadSections: (newSections) => set(state => {
            newSections.forEach(ns => {
                const index = state.sections.findIndex(s => s.id === ns.id);
                if (index !== -1) {
                    state.sections[index] = ns;
                } else {
                    state.sections.push(ns);
                }
            });
        }),
        clearRooms: () => set({ rooms: [], sections: [], past: [], future: [] }),

        // Canvas
        setZoom: (zoom) => set({ zoom: Math.max(0.1, Math.min(5, zoom)) }),
        setPan: (pan) => set({ pan }),
        zoomIn: () => set((state) => ({ zoom: Math.min(5, state.zoom * 1.2) })),
        zoomOut: () => set((state) => ({ zoom: Math.max(0.1, state.zoom / 1.2) })),
        resetView: () => set({ zoom: 1, pan: { x: 0, y: 0 } }),
        toggleGrid: () => set((state) => ({ showGrid: !state.showGrid })),
        toggleSnap: () => set((state) => ({ snapToGrid: !state.snapToGrid })),

        // Selection
        select: (ids) => set({ selectedIds: ids }),
        addToSelection: (id) => set((state) => ({
            selectedIds: [...state.selectedIds, id]
        })),
        clearSelection: () => set({ selectedIds: [], selectedPosition: null }),
        setHovered: (id) => set({ hoveredId: id }),
        setSelectedPosition: (position) => set({ selectedPosition: position }),

        // Room CRUD
        addRoom: (room) => {
            const id = generateId();
            get().saveSnapshot();
            set((state) => {
                state.rooms.push({ ...room, id });
            });
            return id;
        },
        updateRoom: (id, updates) => {
            get().saveSnapshot();
            set((state) => {
                const room = state.rooms.find(r => r.id === id);
                if (room) Object.assign(room, updates);
            });
        },
        deleteRoom: (id) => {
            get().saveSnapshot();
            set((state) => {
                state.rooms = state.rooms.filter(r => r.id !== id);
                state.sections = state.sections.filter(s => s.roomId !== id);
                state.selectedIds = state.selectedIds.filter(sid => sid !== id);
            });
        },
        moveRoom: (id, position) => {
            set((state) => {
                const room = state.rooms.find(r => r.id === id);
                if (room) {
                    if (state.snapToGrid) {
                        const gridPx = state.gridSize * 20; // 20px per foot
                        room.position = {
                            x: Math.round(position.x / gridPx) * gridPx,
                            y: Math.round(position.y / gridPx) * gridPx,
                        };
                    } else {
                        room.position = position;
                    }
                }
            });
        },
        resizeRoom: (id, size) => {
            set((state) => {
                const room = state.rooms.find(r => r.id === id);
                if (room) {
                    if (state.snapToGrid) {
                        const gridPx = state.gridSize * 20;
                        room.size = {
                            width: Math.round(size.width / gridPx) * gridPx,
                            height: Math.round(size.height / gridPx) * gridPx,
                        };
                    } else {
                        room.size = size;
                    }
                }
            });
        },

        // Section CRUD
        addSection: (section) => {
            const id = generateId();
            get().saveSnapshot();
            set((state) => {
                state.sections.push({ ...section, id });
            });
            return id;
        },
        updateSection: (id, updates) => {
            get().saveSnapshot();
            set((state) => {
                const section = state.sections.find(s => s.id === id);
                if (section) Object.assign(section, updates);
            });
        },
        deleteSection: (id) => {
            get().saveSnapshot();
            set((state) => {
                state.sections = state.sections.filter(s => s.id !== id);
            });
        },

        // Tool
        setActiveTool: (tool) => set({ activeTool: tool }),
        setPendingRoomType: (type) => set({ pendingRoomType: type }),

        // History
        saveSnapshot: () => {
            const { rooms, sections, past } = get();
            set({
                past: [...past.slice(-49), { rooms: JSON.parse(JSON.stringify(rooms)), sections: JSON.parse(JSON.stringify(sections)) }],
                future: [],
            });
        },
        undo: () => {
            const { past, rooms, sections } = get();
            if (past.length === 0) return;

            const previous = past[past.length - 1];
            set({
                past: past.slice(0, -1),
                future: [{ rooms: JSON.parse(JSON.stringify(rooms)), sections: JSON.parse(JSON.stringify(sections)) }, ...get().future],
                rooms: previous.rooms,
                sections: previous.sections,
            });
        },
        redo: () => {
            const { future, rooms, sections } = get();
            if (future.length === 0) return;

            const next = future[0];
            set({
                future: future.slice(1),
                past: [...get().past, { rooms: JSON.parse(JSON.stringify(rooms)), sections: JSON.parse(JSON.stringify(sections)) }],
                rooms: next.rooms,
                sections: next.sections,
            });
        },
        canUndo: () => get().past.length > 0,
        canRedo: () => get().future.length > 0,
    }))
);
