import { useState, useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import { apiClient } from '../../../shared/api/client';
import { JSMpegPlayer } from '../components/JSMpegPlayer';
import { Video, LayoutGrid, ChevronDown } from 'lucide-react';
import { useAuth } from '../../../shared/auth/AuthContext';
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors, type DragEndEvent } from '@dnd-kit/core';
import { arrayMove, SortableContext, sortableKeyboardCoordinates, useSortable, rectSortingStrategy } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';

interface Camera {
    id: number;
    name: string;
    ip_address: string;
    port: number;
    username?: string;
    password?: string;
    stream_path?: string;
    transport_mode?: 'tcp' | 'udp' | 'auto';
    rtsp_encoding?: boolean;
    quality?: 'low' | 'medium' | 'original';
    display_order?: number;
    is_active?: boolean | number;
    zone?: string;
}

// Wrap Camera Card with Sortable
function SortableCamera({ camera, children, disabled }: { camera: Camera, children: React.ReactNode, disabled: boolean }) {
    const {
        attributes,
        listeners,
        setNodeRef,
        transform,
        transition,
    } = useSortable({ id: camera.id, disabled });

    const style = {
        transform: CSS.Transform.toString(transform),
        transition,
    };

    return (
        <div ref={setNodeRef} style={style} {...attributes} {...listeners} className={`relative bg-black overflow-hidden border ${disabled ? 'border-slate-800' : 'border-slate-700 hover:border-indigo-500'} transition-colors group h-full w-full`}>
            {children}
        </div>
    );
}

export function MonitoringPage() {
    const { user } = useAuth();
    const [cameras, setCameras] = useState<Camera[]>([]);
    const [activeZone, setActiveZone] = useState<string>('');
    const [availableZones, setAvailableZones] = useState<{ name: string, layout: string }[]>([]);
    const [showLayoutMenu, setShowLayoutMenu] = useState(false);
    const fetchedRef = useRef(false);

    const [streamVersions] = useState<{ [key: number]: number }>({});

    const sensors = useSensors(
        useSensor(PointerSensor),
        useSensor(KeyboardSensor, {
            coordinateGetter: sortableKeyboardCoordinates,
        })
    );

    useEffect(() => {
        if (fetchedRef.current) return;
        fetchedRef.current = true;
        fetchCameras();
    }, []);

    const fetchCameras = async () => {
        try {
            const res = await apiClient.get('/cameras');
            setCameras(res.data);
        } catch (err) {
            console.error('Failed to fetch cameras', err);
        }
    };

    const fetchZones = async () => {
        try {
            const res = await apiClient.get('/cameras/zones');
            const zones = res.data.map((z: any) => ({
                name: z.name,
                layout: z.layout || '2*2'
            }));
            setAvailableZones(zones);

            // Default to the first available zone to show video immediately
            if (!activeZone && zones.length > 0) {
                setActiveZone(zones[0].name);
            }
        } catch (err) {
            console.error('Failed to fetch zones', err);
        }
    };

    // Determine layout based on active zone's setting
    const currentZoneConfig = availableZones.find(z => z.name === activeZone);
    const viewLayout = currentZoneConfig ? currentZoneConfig.layout : '2*2';

    const handleLayoutChange = async (newLayout: string) => {
        if (!activeZone) return;

        // Optimistic UI update
        setAvailableZones(prev => prev.map(z =>
            z.name === activeZone ? { ...z, layout: newLayout } : z
        ));
        setShowLayoutMenu(false);

        try {
            await apiClient.patch(`/cameras/zones/${activeZone}/layout`, { layout: newLayout });
        } catch (err) {
            console.error('Failed to update layout', err);
            // Revert or show alert if needed
        }
    };

    const filteredCameras = !activeZone
        ? []
        : cameras.filter(c => (c.zone || '기본 구역') === activeZone);

    const handleToggleStatus = async (camera: Camera) => {
        // Optimistic UI Update: Calculate new status
        const currentStatus = camera.is_active !== 0 && camera.is_active !== false;
        const newStatus = !currentStatus;

        // Immediately update UI state
        setCameras(prev => prev.map(c =>
            c.id === camera.id ? { ...c, is_active: newStatus ? 1 : 0 } : c
        ));

        try {
            // Send request to server
            await apiClient.patch(`/cameras/${camera.id}/status`, { is_active: newStatus });
            // Only silent fetch to sync eventually, no alert needed
            fetchCameras();
        } catch (err) {
            console.error('Failed to toggle status', err);
            // Revert UI on failure
            setCameras(prev => prev.map(c =>
                c.id === camera.id ? { ...c, is_active: currentStatus ? 1 : 0 } : c
            ));
            alert('상태 변경 실패 (되돌리기)');
        }
    };

    const handleDragEnd = async (event: DragEndEvent) => {
        const { active, over } = event;

        if (over && active.id !== over.id) {
            setCameras((items) => {
                const oldIndex = items.findIndex((item) => item.id === active.id);
                const newIndex = items.findIndex((item) => item.id === over.id);
                const newItems = arrayMove(items, oldIndex, newIndex);

                // Save new order
                apiClient.put('/cameras/reorder', { cameras: newItems.map(c => c.id) })
                    .catch(e => console.error('Failed to save order', e));

                return newItems;
            });
        }
    };

    const getStreamUrl = (cameraId: number) => {
        // Use current host (proxied or direct)
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        const version = streamVersions[cameraId] || 0;
        const url = `${protocol}//${window.location.host}/api/stream?cameraId=${cameraId}&v=${version}`;
        console.log(`[CCTV] Connecting to: ${url}`);
        return url;
    };

    const handlePing = async (id: number) => {
        try {
            const res = await apiClient.get(`/cameras/${id}/ping`);

            // Critical check: If the server returns HTML (catch-all), it's old code
            if (typeof res.data === 'string' && res.data.includes('<html')) {
                alert('❌ Server Sync Error!\nThe production server is still running old code (received HTML instead of JSON).\nPlease re-upload the "server" folder and restart PM2.');
                return;
            }

            if (res.data.success) {
                alert(`✅ Ping Success!\nServer can reach Camera (${res.data.ip}).`);
            } else {
                alert(`❌ Ping Failed!\nServer cannot reach Camera (${res.data.ip || 'Unknown IP'}).\nCheck NAS network/firewall.`);
            }
        } catch (err: any) {
            if (err.response?.status === 404) {
                alert('❌ API Not Found (404)!\nThe server does not have the "ping" feature. Please update and restart the backend.');
            } else {
                alert('Ping API Error. Please check server logs.');
            }
        }
    };

    const checkServerVersion = async () => {
        try {
            const res = await apiClient.get('/health');
            console.log('[System] Server Version:', res.data);
        } catch (e) {
            console.warn('[System] Could not fetch server health - might be old version.');
        }
    };

    useEffect(() => {
        fetchCameras();
        fetchZones();
        checkServerVersion();
    }, []);


    const HeaderDropdown = () => {
        const portalRoot = document.getElementById('header-portal-root');
        if (!portalRoot) return null;

        // Tabs: [Zones...] 
        const zoneTabs = availableZones.map(z => z.name);
        const layoutOptions = [
            { id: '1', label: '1개', icon: <div className="w-4 h-4 border border-white/40" /> },
            { id: '1*2', label: '1*2', icon: <div className="w-4 h-4 border border-white/40 flex"><div className="w-1/2 border-r border-white/40" /></div> },
            { id: '2*2', label: '2*2', icon: <div className="w-4 h-4 border border-white/40 grid grid-cols-2 grid-rows-2"><div className="border-r border-b border-white/40" /><div className="border-b border-white/40" /><div className="border-r border-white/40" /></div> },
            { id: '3*3', label: '3*3', icon: <div className="w-4 h-4 border border-white/40 grid grid-cols-3 grid-rows-3"><div className="border-r border-b border-white/40" /><div className="border-r border-b border-white/40" /><div className="border-b border-white/40" /><div className="border-r border-b border-white/40" /><div className="border-r border-b border-white/40" /><div className="border-b border-white/40" /></div> },
            { id: '4*4', label: '4*4', icon: <div className="w-4 h-4 border border-white/40 grid grid-cols-4 grid-rows-4" /> },
            { id: '5*5', label: '5*5', icon: <div className="w-4 h-4 border border-white/40 grid grid-cols-5 grid-rows-5" /> },
            { id: '6*6', label: '6*6', icon: <div className="w-4 h-4 border border-white/40 grid grid-cols-6 grid-rows-6" /> }
        ];

        return createPortal(
            <div className="flex items-center w-full h-full pointer-events-none">
                {/* Left Area: Zone Tabs */}
                <div className="flex gap-1 h-full items-end pb-1 overflow-x-auto scrollbar-hide pointer-events-auto border-l border-slate-200 ml-4 pl-4">
                    {zoneTabs.map(name => (
                        <button
                            key={name}
                            onClick={() => setActiveZone(name)}
                            className={`px-4 py-2 text-[13px] font-bold transition-all border-b-2 whitespace-nowrap ${activeZone === name
                                ? 'text-indigo-600 border-indigo-600 bg-indigo-50/20'
                                : 'text-slate-400 border-transparent hover:text-slate-600'
                                }`}
                        >
                            {name}
                        </button>
                    ))}
                </div>

                {/* Spacer to push everything else to the right */}
                <div className="flex-1" />

                {/* Right Area: Layout Selector */}
                <div className="px-3 pointer-events-auto flex items-center">
                    <div className="relative">
                        <button
                            onClick={() => setShowLayoutMenu(!showLayoutMenu)}
                            className={`flex items-center gap-2 px-3 py-1.5 rounded-lg text-[11px] font-bold transition-all border ${showLayoutMenu ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-slate-50 text-slate-600 border-slate-200 hover:border-indigo-400'} ${!activeZone ? 'opacity-50 grayscale cursor-not-allowed' : ''}`}
                            disabled={!activeZone}
                        >
                            <LayoutGrid size={14} />
                            레이아웃: {!activeZone ? '--' : viewLayout}
                            <ChevronDown size={14} className={`transition-transform duration-200 ${showLayoutMenu ? 'rotate-180' : ''}`} />
                        </button>

                        {showLayoutMenu && activeZone && (
                            <div className="absolute right-0 top-full mt-2 w-48 bg-[#1a1a1a] rounded-xl shadow-2xl border border-white/10 p-2 z-[100] animate-in fade-in zoom-in duration-200">
                                <div className="px-2 py-1.5 text-[9px] font-bold text-white/30 uppercase tracking-[0.2em] border-b border-white/5 mb-1">
                                    Monitor Arrangement
                                </div>
                                <div className="grid grid-cols-2 gap-1">
                                    {layoutOptions.map(opt => (
                                        <button
                                            key={opt.id}
                                            onClick={() => handleLayoutChange(opt.id)}
                                            className={`flex items-center gap-3 px-3 py-2.5 rounded-lg text-[11px] font-medium transition-all ${viewLayout === opt.id ? 'bg-indigo-600 text-white' : 'text-white/60 hover:bg-white/5 hover:text-white'}`}
                                        >
                                            <div className="w-4 flex justify-center opacity-60">{opt.icon}</div>
                                            {opt.label}
                                        </button>
                                    ))}
                                </div>
                            </div>
                        )}
                    </div>
                </div>
            </div>,
            portalRoot
        );
    };

    const getLayoutInfo = () => {
        if (viewLayout === '1') return { cols: 'grid-cols-1', total: 1 };
        if (viewLayout === '1*2') return { cols: 'grid-cols-2', total: 2 };

        // Multi-grid like 2*2, 3*3, 4*4
        const parts = viewLayout.split('*');
        if (parts.length === 2) {
            const n = parseInt(parts[0]);
            return { cols: `grid-cols-${n}`, total: n * n };
        }

        return { cols: 'grid-cols-2', total: 4 };
    };

    const layoutInfo = getLayoutInfo();
    const totalSlots = Math.max(layoutInfo.total, filteredCameras.length);
    // Fill slots: actual cameras + empty placeholders if needed to complete the grid rows
    const slots = Array.from({ length: totalSlots }).map((_, i) => filteredCameras[i] || null);

    return (
        <div className="w-full h-full bg-[#0a0a0a] flex flex-col min-h-0">
            <HeaderDropdown />

            <div className="flex-1 p-2 overflow-hidden flex flex-col min-h-0">
                <DndContext
                    sensors={sensors}
                    collisionDetection={closestCenter}
                    onDragEnd={handleDragEnd}
                >
                    <SortableContext
                        items={filteredCameras.map(c => c.id)}
                        strategy={rectSortingStrategy}
                        disabled={true}
                    >
                        <div className={`grid h-full w-full gap-1 ${layoutInfo.cols} ${totalSlots > layoutInfo.total ? 'overflow-y-auto' : ''}`}
                            style={{ gridAutoRows: (viewLayout === '1' || viewLayout === '1*2') ? '100%' : `${100 / Math.sqrt(layoutInfo.total)}%` }}>
                            {slots.map((camera, index) => (
                                <div key={camera ? camera.id : `empty-${index}`} className="h-full w-full">
                                    {camera ? (
                                        <SortableCamera camera={camera} disabled={true}>
                                            <div className="relative w-full h-full flex flex-col group text-white/90">
                                                {/* VMS Slot Header */}
                                                <div className="absolute top-0 left-0 right-0 z-10 bg-black/40 backdrop-blur-sm border-b border-white/5 px-3 py-1.5 flex justify-between items-center opacity-0 group-hover:opacity-100 transition-opacity">
                                                    <div className="flex items-center gap-2">
                                                        <div className={`w-2 h-2 rounded-full ${(camera.is_active !== 0 && camera.is_active !== false) ? 'bg-green-500 animate-pulse' : 'bg-red-500'}`}></div>
                                                        <span className="text-[11px] font-bold truncate max-w-[150px]">{camera.name}</span>
                                                    </div>

                                                    {(user?.role === 'admin' || user?.role === 'supervisor') && (
                                                        <div className="flex gap-1" onPointerDown={(e) => e.stopPropagation()}>
                                                            <button
                                                                onClick={() => handlePing(camera.id)}
                                                                className="p-1 text-white/50 hover:text-green-400 transition-colors"
                                                                title="Ping"
                                                            >
                                                                <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="m21 2-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0 3 3L22 7l-3-3L15.5 7.5z" /></svg>
                                                            </button>
                                                            <button
                                                                onClick={() => handleToggleStatus(camera)}
                                                                className={`p-1 transition-colors ${(camera.is_active !== 0 && camera.is_active !== false) ? 'text-white/50 hover:text-orange-400' : 'text-white/50 hover:text-green-400'}`}
                                                                title={(camera.is_active !== 0 && camera.is_active !== false) ? "Pause" : "Play"}
                                                            >
                                                                {(camera.is_active !== 0 && camera.is_active !== false) ? (
                                                                    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>
                                                                ) : (
                                                                    <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>
                                                                )}
                                                            </button>
                                                        </div>
                                                    )}
                                                </div>

                                                {/* Streaming Video */}
                                                <div className="flex-1 bg-black flex items-center justify-center">
                                                    <JSMpegPlayer
                                                        key={`${camera.id}-${streamVersions[camera.id] || 0}`}
                                                        url={getStreamUrl(camera.id)}
                                                        className="w-full h-full object-contain"
                                                    />
                                                </div>

                                                {/* Small persistent ID or Name overlay */}
                                                <div className="absolute bottom-2 left-2 px-2 py-0.5 bg-black/60 rounded text-[10px] text-white/30 font-mono pointer-events-none border border-white/5">
                                                    CH {index + 1} | {camera.ip_address}
                                                </div>
                                            </div>
                                        </SortableCamera>
                                    ) : (
                                        <div className="h-full w-full bg-[#121212] border border-slate-900/50 flex flex-col items-center justify-center text-slate-700 select-none">
                                            <Video size={32} className="opacity-10 mb-2" />
                                            <span className="text-[11px] font-bold opacity-20 uppercase tracking-widest">No Buffer</span>
                                        </div>
                                    )}
                                </div>
                            ))}
                        </div>
                    </SortableContext>
                </DndContext>
            </div>
        </div>
    );
}
