import React, { useState, useEffect, useRef } from 'react';
import AppLayout from '@/Layouts/AppLayout';
import { Stage, Layer, Rect, Image as KonvaImage, Text, Transformer } from 'react-konva';
import useImage from 'use-image';
import axios from 'axios';
import {StockRoom, LayoutItem, LayoutLine, StockRack, StockLine, StockPosition} from '@/types';
import RackModalDetails from "@/Components/RackModalDetails";
import EditStockSections from '@/Components/modals/EditStockSections';

const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');

export default function FloorPlan() {

    // at the top of FloorPlan()
    const [showEditSectionsModal, setShowEditSectionsModal] = useState(false);
    const [selectedPositionForEditing, setSelectedPositionForEditing] = useState<StockPosition | null>(null);

    // fire this when RackModalDetails tells us “user clicked a position”
    const handleOpenSections = async (posId: number) => {
        try {
            console.log(posId);
            // 1️⃣ pull down the fresh position (with capacity & sections)
            const { data: freshPos } = await axios.get<StockPosition>(
                `/api/stockPositions/${posId}`,
                { withCredentials: true }
            );
            // 2️⃣ stash it & open the modal
            setSelectedPositionForEditing(freshPos);
            setShowEditSectionsModal(true);
        } catch (err) {
            console.error(err);
            alert('Could not load position details. Please try again.');
        }
    };

// pass this into EditStockSections so that onClose we go back to RackModalDetails
    const handleCloseSections = () => {
        setShowEditSectionsModal(false);
    };

    // Rooms & selected room
    const [rooms, setRooms] = useState<StockRoom[]>([]);
    const [selectedRoom, setSelectedRoom] = useState<StockRoom | null>(null);

    // Layout data
    const [layoutItems, setLayoutItems] = useState<LayoutItem[]>([]);
    const [layoutLines, setLayoutLines] = useState<LayoutLine[]>([]);
    const [bgFile, setBgFile] = useState<string | null>(null);

    // Track which existing DB items were deleted client-side
    const [deletedLineDbIds, setDeletedLineDbIds] = useState<number[]>([]);
    const [deletedRackDbIds, setDeletedRackDbIds] = useState<number[]>([]);

    // New-layout modal state
    const [showCreateModal, setShowCreateModal] = useState(false);
    const [newBgFile, setNewBgFile] = useState<string | null>(null);

    // Edit-item modal state
    const [editModal, setEditModal] = useState({
        type: 'rack' as 'rack' | 'line' | null,
        item: null as LayoutItem | LayoutLine | null,
        item_obj: null as StockLine | StockRack | null,
        visible: false,
        name: '',
        symbol: ''
    });

    // Konva refs & selection
    const layerRef = useRef<any>(null);
    const transformerRef = useRef<any>(null);
    const [selectedId, setSelectedId] = useState<string | null>(null);
    const [selectedType, setSelectedType] = useState<'rack' | 'line' | null>(null);

    // Background image for canvas
    const [bgImage] = useImage(bgFile || '');

    // Fetch room list on mount
    useEffect(() => {
        axios.get('/api/rooms')
            .then(({ data }) => {
                setRooms(data.rooms);
                if (data.rooms.length) setSelectedRoom(data.rooms[0]);
            })
            .catch(console.error);
    }, []);

    useEffect(() => {
        if (!showEditSectionsModal && selectedRoom) {
            loadLayout(selectedRoom.room_id);
        }
    }, [showEditSectionsModal, selectedRoom]);

    useEffect(() => {
        if (!showEditSectionsModal && editModal.visible && editModal.type === 'rack' && editModal.item_obj) {
            // grab the just-saved rack by its ID:
            axios.get<StockRack>(`/api/stock-racks/${(editModal.item_obj as StockRack).rack_id}`, {
                withCredentials: true
            })
                .then(({ data: freshRack }) => {
                    setEditModal(m => ({ ...m, item_obj: freshRack }));
                })
                .catch(err => {
                    console.error('Could not refresh rack details:', err);
                });
        }
    }, [showEditSectionsModal, editModal.visible]);

    // Load a room's layout (or show create modal)
    const loadLayout = async (roomId: number) => {
        try {
            const { data } = await axios.get(`/api/floor-layouts/${roomId}`);
            if (!data.layoutItems) {
                setShowCreateModal(true);
            } else {
                setLayoutItems(data.layoutItems.racks || []);
                setLayoutLines(data.layoutItems.lines || []);
                setBgFile(data.bgFile || null);
                setShowCreateModal(false);
                // reset deletion trackers
                setDeletedLineDbIds([]);
                setDeletedRackDbIds([]);
            }
        } catch {
            setShowCreateModal(true);
        }
    };

    // Reload layout whenever selectedRoom changes
    useEffect(() => {
        if (selectedRoom) loadLayout(selectedRoom.room_id);
    }, [selectedRoom]);

    // Hook up the Konva Transformer to the selected shape
    useEffect(() => {
        const tr = transformerRef.current;
        if (!tr) return;
        if (selectedId) {
            const node = layerRef.current.findOne(`#${selectedId}`);
            node ? tr.nodes([node]) : tr.nodes([]);
        } else {
            tr.nodes([]);
        }
        tr.getLayer().batchDraw();
    }, [selectedId]);

    // AABB intersection for rack-on-line test
    const intersects = (r: LayoutItem, l: LayoutLine) =>
        r.x + r.width >= l.x && r.x <= l.x + l.width &&
        r.y + r.height >= l.y && r.y <= l.y + l.height;

    // Selection handler
    const onSelect = (e: any, id: string, type: 'rack' | 'line') => {
        e.cancelBubble = true;
        setSelectedId(id);
        setSelectedType(type);
    };

    // Drag end handler
    const onDragEnd = (e: any, id: string, type: 'rack' | 'line') => {
        const { x, y } = e.target.position();
        if (type === 'line') {
            setLayoutLines(ls => ls.map(l => l.id === id ? { ...l, x, y } : l));
        } else {
            setLayoutItems(is => is.map(i => {
                if (i.id === id) {
                    const upd = { ...i, x, y };
                    const hit = layoutLines.find(l => intersects(upd, l));
                    upd.lineId = hit?.id ?? null;
                    return upd;
                }
                return i;
            }));
        }
    };

    // Transform end handler
    const onTransformEnd = (e: any, id: string) => {
        const node = e.target;
        const scaleX = node.scaleX(), scaleY = node.scaleY();
        const w = Math.max(5, node.width() * scaleX);
        const h = Math.max(5, node.height() * scaleY);
        node.scaleX(1); node.scaleY(1);

        if (selectedType === 'line') {
            setLayoutLines(ls => ls.map(l => l.id === id ? {
                ...l, x: node.x(), y: node.y(), width: w, height: h
            } : l));
        } else {
            setLayoutItems(is => is.map(i => i.id === id ? {
                ...i, x: node.x(), y: node.y(), width: w, height: h
            } : i));
        }
    };

    // Helpers for new symbols/numbers
    const nextLineLetter = () => {
        const used = new Set<string>();
        selectedRoom?.lines.forEach(l => used.add(l.line_symbol));
        layoutLines.forEach(l => used.add(l.symbol));
        for (let c of ALPHABET) if (!used.has(c)) return c;
        return ALPHABET[0];
    };
    const nextRackNumber = (lineId: string) => {
        const nums = layoutItems
            .filter(i => i.lineId === lineId)
            .map(i => parseInt(i.symbol) || 0);
        return (nums.length ? Math.max(...nums) : 0) + 1;
    };

    // Add new line
    const addLine = () => {
        const letter = nextLineLetter();
        const id = `line-${Date.now()}`;
        setLayoutLines(ls => [...ls, {
            id, dbId: null,
            name: `Line ${letter}`, symbol: letter,
            x: 100, y: 100, width: 200, height: 20, fill: 'lightblue'
        }]);
        setSelectedId(id);
        setSelectedType('line');
    };

    // Add new rack
    const addRack = () => {
        if (!selectedId || selectedType !== 'line') {
            return alert('Select a line first');
        }
        const line = layoutLines.find(l => l.id === selectedId)!;
        const num = nextRackNumber(line.id);
        const id = `rack-${Date.now()}`;
        setLayoutItems(is => [...is, {
            id, dbId: null,
            name: `Rack ${num}`, symbol: String(num),
            x: line.x + 10, y: line.y + line.height + 10,
            width: 60, height: 60, fill: 'yellow',
            lineId: line.id
        }]);
        setSelectedId(id);
        setSelectedType('rack');
    };

    // Open edit modal
    const openEditModal = (item: any, type: 'rack' | 'line') => {
        const item_obj = type === 'line'
            ? selectedRoom?.lines?.find(l => l.line_id === item.dbId) ?? null
            : selectedRoom
            ?.lines
            ?.flatMap(l => l.racks || [])
            .find(r => r.rack_id === item.dbId) ?? null;

        setEditModal({
            type,
            item,
            item_obj,
            visible: true,
            name: item.name,
            symbol: item.symbol
        });
    };

    // Save name/symbol edits
    const saveEdit = async () => {
        if (!editModal.item) return;
        const { type, item, name, symbol } = editModal;
        try {
            if (type === 'line') {
                let res;
                if (item.dbId) {
                    res = await axios.put(`/api/stock-lines/${item.dbId}`, {
                        line_name: name,
                        line_symbol: symbol
                    });
                } else {
                    res = await axios.post('/api/stock-lines', {
                        room_id: selectedRoom?.room_id,
                        line_name: name,
                        line_symbol: symbol
                    });
                }
                const dbId = res.data.line_id;
                setLayoutLines(ls => ls.map(l =>
                    l.id === item.id ? { ...l, name, symbol, dbId } : l
                ));
            } else {
                await axios.put(`/api/stock-racks/${item.dbId}`, {
                    rack_name: name,
                    rack_symbol: symbol
                });
                setLayoutItems(is => is.map(i =>
                    i.id === item.id ? { ...i, name, symbol } : i
                ));
            }
            setEditModal(m => ({ ...m, visible: false }));
        } catch (e) {
            console.error(e);
            alert('Error saving');
        }
    };

    // Delete rack or line (mark for later DB delete + remove visually)
    const deleteItem = () => {
        if (!editModal.item) return;
        const { type, item } = editModal;

        if (type === 'line') {
            // if it existed in DB, queue it
            if (item.dbId) {
                setDeletedLineDbIds(ids => [...ids, item.dbId!]);
                // also queue any racks under this line
                layoutItems
                    .filter(r => r.lineId === item.id && r.dbId)
                    .forEach(r => setDeletedRackDbIds(ids => [...ids, r.dbId!]));
            }
            // remove the line and its racks visually
            setLayoutLines(ls => ls.filter(l => l.id !== item.id));
            setLayoutItems(is => is.filter(i => i.lineId !== item.id));
        } else {
            if (item.dbId) {
                setDeletedRackDbIds(ids => [...ids, item.dbId!]);
            }
            setLayoutItems(is => is.filter(i => i.id !== item.id));
        }

        setEditModal(m => ({ ...m, visible: false }));
    };

    // Create new layout
    const createLayout = async () => {
        if (!selectedRoom) return;
        try {
            const defaultName = `${selectedRoom.room_name} layout`;
            const form = new FormData();
            form.append('room_id', String(selectedRoom.room_id));
            form.append('name', defaultName);
            if (newBgFile) form.append('bgFile', newBgFile);

            await axios.post('/api/floor-layouts/create', form, {
                headers: { 'Content-Type': 'multipart/form-data' }
            });

            setShowCreateModal(false);
            setNewBgFile(null);
            await loadLayout(selectedRoom.room_id);
        } catch (e) {
            console.error(e);
            alert('Error creating layout');
        }
    };

    // --- ENHANCED saveLayout: handle creates, deletes, then update layout record ---
    const saveLayout = async () => {
        if (layoutItems.some(r => !r.lineId)) {
            return alert('Place all racks on lines before saving.');
        }

        try {
            // 1️⃣ Create any new lines
            await Promise.all(layoutLines.map(async line => {
                if (!line.dbId) {
                    const { data } = await axios.post('/api/stock-lines', {
                        room_id: selectedRoom!.room_id,
                        line_symbol: line.symbol,
                        line_name: line.name
                    });
                    line.dbId = data.line_id;
                }
            }));

            // 2️⃣ Create any new racks
            await Promise.all(layoutItems.map(async rack => {
                if (!rack.dbId) {
                    const parentLine = layoutLines.find(l => l.id === rack.lineId)!;
                    const { data } = await axios.post('/api/stock-racks', {
                        line_id: parentLine.dbId,
                        rack_symbol: rack.symbol,
                        rack_name: rack.name
                    });
                    rack.dbId = data.rack_id;
                }
            }));

            // 3️⃣ Update any existing rack whose parent‐line changed
            await Promise.all( layoutItems
                .filter(r => r.dbId !== null)
                .map(async rack => {
                    const parent = layoutLines.find(l => l.id === rack.lineId)!;
                    // send only if rack.line_id in DB !== parent.dbId
                    // (you could cache original in state, but simplest to just PUT all)
                    await axios.put(`/api/stock-racks/${rack.dbId}`, {
                        line_id: parent.dbId,
                        // you can also include name/symbol if you like:
                        rack_name: rack.name,
                        rack_symbol: rack.symbol,
                    });
                })
            );

            // 3️⃣ Delete any queued lines/racks
            await Promise.all([
                ...deletedLineDbIds.map(id => axios.delete(`/api/stock-lines/${id}`)),
                ...deletedRackDbIds.map(id => axios.delete(`/api/stock-racks/${id}`))
            ]);

            // reset the deletion queues
            setDeletedLineDbIds([]);
            setDeletedRackDbIds([]);

            // 4️⃣ Persist the full geometry
            const { data } = await axios.post('/api/floor-layouts/update', {
                room_id: selectedRoom!.room_id,
                contents: {
                    lines: layoutLines,
                    racks: layoutItems
                }
            });

            alert(`Layout saved at ${new Date(data.updated_at).toLocaleTimeString()}`);
        } catch (e) {
            console.error(e);
            alert('Error saving layout');
        }
    };


    // ➊ add a new shelf
    const handleAddShelf = async (rackId: number) => {
        // compute next symbol & name from current editModal.item_obj
        const rack = editModal.item_obj as StockRack;
        const next = rack.shelves ? rack.shelves.length + 1 : 1;
        const symbol = String(next);
        const name = `Shelf ${symbol}`;

        try {
            await axios.post(
                '/api/stock-shelves',
                { rack_id: rackId, shelf_symbol: symbol, shelf_name: name },
                { withCredentials: true }
            );
            // refresh just that rack
            const { data: freshRack } = await axios.get<StockRack>(
                `/api/stock-racks/${rackId}`,
                { withCredentials: true }
            );
            setEditModal(m => ({ ...m, item_obj: freshRack }));
        } catch (err) {
            console.error(err);
            alert('Could not add shelf.');
        }
    };

// ➋ delete a shelf
    const handleDeleteShelf = async (shelfId: number) => {
        try {
            await axios.delete(`/api/stock-shelves/${shelfId}`, {
                withCredentials: true
            });
            // after delete, re-fetch rack
            const rack = editModal.item_obj as StockRack;
            const { data: freshRack } = await axios.get<StockRack>(
                `/api/stock-racks/${rack.rack_id}`,
                { withCredentials: true }
            );
            setEditModal(m => ({ ...m, item_obj: freshRack }));
        } catch (err) {
            console.error(err);
            alert('Could not delete shelf.');
        }
    };

    return (
        <AppLayout title="Floor Plan">
            <div className="p-6 flex flex-col items-center space-y-4">
                {/* Toolbar */}
                <div className="w-full flex justify-between items-center mb-4">
                    <div className="tabs">
                        {rooms.map(r => (
                            <button
                                key={r.room_id}
                                className={`tab ${selectedRoom?.room_id === r.room_id ? 'tab-active' : ''}`}
                                onClick={() => setSelectedRoom(r)}
                            >
                                {r.room_name}
                            </button>
                        ))}
                    </div>
                    <div>
                        <button className="btn mr-2" onClick={addLine}>Add Line</button>
                        <button className="btn mr-2" onClick={addRack}>Add Rack</button>
                        <button className="btn mr-2" onClick={() => setShowCreateModal(true)}>New Layout</button>
                        <button className="btn" onClick={saveLayout}>Save Layout</button>
                    </div>
                </div>

                {/* Canvas */}
                <Stage width={1300} height={900} onClick={() => setSelectedId(null)}>
                    <Layer ref={layerRef}>
                        <Rect x={0} y={0} width={1300} height={900} fill="white" />
                        {bgImage && (
                            <KonvaImage
                                image={bgImage}
                                x={0} y={0}
                                width={1300} height={900}
                                listening={false}
                            />
                        )}

                        {/* Lines */}
                        {layoutLines.map(line => (
                            <React.Fragment key={line.id}>
                                <Rect
                                    id={line.id}
                                    x={line.x} y={line.y}
                                    width={line.width} height={line.height}
                                    fill={line.fill} stroke="black"
                                    draggable
                                    onClick={e => { onSelect(e, line.id, 'line'); openEditModal(line, 'line'); }}
                                    onDragEnd={e => onDragEnd(e, line.id, 'line')}
                                    onTransformEnd={e => onTransformEnd(e, line.id)}
                                />
                                <Text text={line.name} x={line.x + 5} y={line.y + 2} fontSize={14} />
                            </React.Fragment>
                        ))}

                        {/* Racks */}
                        {layoutItems.map(item => (
                            <React.Fragment key={item.id}>
                                <Rect
                                    id={item.id}
                                    x={item.x} y={item.y}
                                    width={item.width} height={item.height}
                                    fill={item.fill}
                                    stroke={item.lineId ? 'black' : 'red'}
                                    strokeWidth={item.lineId ? 1 : 2}
                                    draggable
                                    onClick={e => { onSelect(e, item.id, 'rack'); openEditModal(item, 'rack'); }}
                                    onDragEnd={e => onDragEnd(e, item.id, 'rack')}
                                    onTransformEnd={e => onTransformEnd(e, item.id)}
                                />
                                <Text text={item.name} x={item.x + 5} y={item.y + 5} fontSize={14} />
                            </React.Fragment>
                        ))}

                        <Transformer ref={transformerRef} />
                    </Layer>
                </Stage>

                {/* Edit Modal */}
                {editModal.visible && (
                    <div className="modal modal-open">
                        <div className="modal-box max-w-[50%]">
                            <h3 className="font-bold text-lg">Edit {editModal.type}</h3>
                            <input
                                type="text"
                                className="input w-full my-2"
                                value={editModal.name}
                                onChange={e => setEditModal(m => ({ ...m, name: e.target.value }))}
                                placeholder="Name"
                            />
                            <input
                                type="text"
                                className="input w-full my-2"
                                value={editModal.symbol}
                                onChange={e => setEditModal(m => ({ ...m, symbol: e.target.value }))}
                                placeholder="Symbol"
                            />
                            {editModal.type === 'rack' && (
                                <div className="mt-4">
                                    <h4 className="font-bold mb-2">Shelves &amp; Sections</h4>
                                    <RackModalDetails rack={editModal.item_obj} onPositionClick={handleOpenSections} onAddShelf={handleAddShelf} onDeleteShelf={handleDeleteShelf} />
                                </div>
                            )}
                            <div className="modal-action">
                                <button className="btn" onClick={saveEdit}>Save</button>
                                <button className="btn btn-error" onClick={deleteItem}>Delete</button>
                                <button className="btn btn-outline" onClick={() => setEditModal(m => ({ ...m, visible: false }))}>Cancel</button>
                            </div>
                        </div>
                    </div>
                )}

                {/* === Sections Editor Nested Modal === */}
                {showEditSectionsModal && selectedPositionForEditing && (
                    <div className="modal modal-open">
                        <div className="modal-box max-w-[50%]">
                            <EditStockSections
                                selectedPosition={selectedPositionForEditing}
                                onClose={handleCloseSections}
                            />
                        </div>
                    </div>
                )}

                {/* Create Layout Modal */}
                {showCreateModal && (
                    <div className="modal modal-open">
                        <div className="modal-box">
                            <h3 className="font-bold text-lg">New Layout for {selectedRoom?.room_name}</h3>
                            <h3 className="text-secondary">Layout does not exist yet, upload floorplan and create</h3>
                            <input
                                type="file"
                                accept="image/*"
                                className="file-input w-full my-2"
                                onChange={e => {
                                    const file = e.target.files?.[0];
                                    if (!file) return;
                                    const reader = new FileReader();
                                    reader.onload = () => setNewBgFile(reader.result as string);
                                    reader.readAsDataURL(file);
                                }}
                            />
                            {newBgFile && (
                                <img src={newBgFile} alt="Preview" className="w-full mb-2 rounded" />
                            )}
                            <div className="modal-action">
                                <button
                                    className="btn btn-primary"
                                    onClick={createLayout}
                                    disabled={!newBgFile}
                                >
                                    Create
                                </button>
                                <button
                                    className="btn btn-outline"
                                    onClick={() => {
                                        setShowCreateModal(false);
                                        setNewBgFile(null);
                                    }}
                                >
                                    Cancel
                                </button>
                            </div>
                        </div>
                    </div>
                )}

            </div>
        </AppLayout>
    );
}
