import React, { useState, useEffect, useRef } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from "recharts";

type ChatMessage = {
    role: 'user' | 'system';
    content: string;
};

const App: React.FC = () => {
    const [urlInput, setUrlInput] = useState<string>('https://www.example.com');
    const [bulkToggle, setBulkToggle] = useState<boolean>(false);
    const [actionRadio, setActionRadio] = useState<'Scrape data' | 'Capture image' | 'Both'>('Both');
    const [maxUrls, setMaxUrls] = useState<number>(5);
    const [crawlDepth, setCrawlDepth] = useState<number>(1);
    const [scrapedDataOutput, setScrapedDataOutput] = useState<string>('');
    const [screenshotOutput, setScreenshotOutput] = useState<string | null>(null);
    const [monitorUrlInput, setMonitorUrlInput] = useState<string>('');
    const [intervalInput, setIntervalInput] = useState<number>(300);
    const [changeOutput, setChangeOutput] = useState<string>('');
    const [chatHistory, setChatHistory] = useState<ChatMessage[]>([]);
    const [isMonitoring, setIsMonitoring] = useState<boolean>(false);
    const [monitoringData, setMonitoringData] = useState<{ time: string; changes: number }[]>([]);
    const [isProcessing, setIsProcessing] = useState<boolean>(false);
    const [error, setError] = useState<string | null>(null);
    const wsRef = useRef<WebSocket | null>(null);

    useEffect(() => {
        let ws: WebSocket | null = null;

        if (isMonitoring) {
            ws = new WebSocket('ws://localhost:8000/ws');
            wsRef.current = ws;

            ws.onopen = () => {
                console.log("Connected to WebSocket server.");
            };

            ws.onmessage = (event) => {
                const message = JSON.parse(event.data);
                if (message.type === "change_detected") {
                     setChangeOutput(prev => prev + `Change detected at ${message.url}\n`);
                    setChatHistory(prev => [...prev, { role: 'system', content: `Change detected at ${message.url}` }]);
                    setMonitoringData(prev => {
                        const now = new Date();
                        const time = now.toLocaleTimeString();
                        return [...prev, { time, changes: 1 }];
                    });
                } else if (message.type === "server_log") {
                    console.log("Server Log:", message.log);
                } else if (message.type === "server_error") {
                    setError(message.error);
                }
            };

            ws.onclose = () => {
                console.log("Disconnected from WebSocket server.");
            };

            ws.onerror = (error) => {
                console.error("WebSocket error:", error);
                setError("WebSocket connection error.");
            };
        } else if (wsRef.current) {
            wsRef.current.close();
            wsRef.current = null;
        }

         return () => {
            if (wsRef.current) {
                wsRef.current.close();
            }
        };
    }, [isMonitoring]);
    

    const handleProcessUrls = async () => {
         setIsProcessing(true);
        setError(null);
        try {
        const response = await fetch('http://localhost:8000/process_urls', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    url_input: urlInput,
                    bulk_toggle: bulkToggle,
                    action_radio: actionRadio,
                    max_urls: maxUrls,
                    crawl_depth: crawlDepth,
                }),
            });

            if (!response.ok) {
                const errorData = await response.json();
                throw new Error(`HTTP error! Status: ${response.status}, Message: ${errorData.message || 'Unknown error'}`);
            }
           const data = await response.json();
            setScrapedDataOutput(JSON.stringify(data.scraped_data, null, 2));
            if (data.screenshot_data) {
                setScreenshotOutput(data.screenshot_data);
            } else {
                 setScreenshotOutput(null);
             }
             setError(null);
        } catch (e: any) {
            console.error("Error processing URLs:", e);
            setError(e.message);
            setScrapedDataOutput('');
            setScreenshotOutput(null);
        } finally {
           setIsProcessing(false);
        }
    };

   const handleChatSubmit = async (user_input: string) => {
        setChatHistory(prev => [...prev, { role: 'user', content: user_input }]);
        if (user_input.toLowerCase().includes("start monitoring")) {
            setIsMonitoring(true);
             setChatHistory(prev => [...prev, { role: 'system', content: "Monitoring started." }]);
        } else if (user_input.toLowerCase().includes("stop monitoring")) {
            setIsMonitoring(false);
             setChatHistory(prev => [...prev, { role: 'system', content: "Monitoring stopped." }]);
        } else if (user_input.toLowerCase().includes("help")) {
            setChatHistory(prev => [...prev, { role: 'system', content: "Commands: 'Start monitoring', 'Stop monitoring', 'Help'" }]);
        } else {
            setChatHistory(prev => [...prev, { role: 'system', content: "Unknown command. Type 'Help' for available commands." }]);
        }
    };

    const handleStartMonitoring = () => {
        setIsMonitoring(true);
        setChatHistory(prev => [...prev, { role: 'system', content: "Monitoring started." }]);
    };

    const handleStopMonitoring = () => {
        setIsMonitoring(false);
        setChatHistory(prev => [...prev, { role: 'system', content: "Monitoring stopped." }]);
        setMonitoringData([]);
    };

    return (
        <div className="bg-gray-100 min-h-screen p-4">
            <h1 className="text-3xl font-bold text-center text-gray-800 mb-8">Smart Scraper with Change Detection</h1>
            {error && <div className="bg-red-200 text-red-700 rounded-md p-2 mb-4">{error}</div>}

            <div className="flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4">

                <div className="bg-white rounded-lg shadow-md p-4 flex-1">
                    <h2 className="text-xl font-semibold mb-4 text-gray-700">URL Scrape/Screenshot</h2>
                    <div className="mb-2">
                        <label className="block text-gray-700 text-sm font-bold mb-2">Enter URL(s)</label>
                        <textarea
                            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                            value={urlInput}
                            onChange={(e) => setUrlInput(e.target.value)}
                        />
                    </div>
                    <div className="flex items-center space-x-4 mb-2">
                         <label className="block text-gray-700 text-sm font-bold">Bulk URLs</label>
                        <input type="checkbox" className="form-checkbox h-5 w-5 text-indigo-600" checked={bulkToggle} onChange={() => setBulkToggle(!bulkToggle)} />
                   </div>
                   <div className="mb-2">
                        <label className="block text-gray-700 text-sm font-bold mb-2">Select Action</label>
                        <div className="space-x-4 flex">
                            <label className="flex items-center space-x-2">
                                <input type="radio" className="form-radio h-4 w-4 text-indigo-600" value="Scrape data" checked={actionRadio === "Scrape data"} onChange={() => setActionRadio("Scrape data")} />
                                <span className="text-gray-700 text-sm">Scrape data</span>
                            </label>
                            <label className="flex items-center space-x-2">
                                <input type="radio" className="form-radio h-4 w-4 text-indigo-600" value="Capture image" checked={actionRadio === "Capture image"} onChange={() => setActionRadio("Capture image")} />
                                <span className="text-gray-700 text-sm">Capture image</span>
                            </label>
                            <label className="flex items-center space-x-2">
                                <input type="radio" className="form-radio h-4 w-4 text-indigo-600" value="Both" checked={actionRadio === "Both"} onChange={() => setActionRadio("Both")} />
                                <span className="text-gray-700 text-sm">Both</span>
                            </label>
                        </div>
                    </div>
                    <div className="mb-2">
                        <label className="block text-gray-700 text-sm font-bold mb-2">Max URLs to process</label>
                        <input type="range" className="form-range w-full" min={1} max={1000} value={maxUrls} onChange={(e) => setMaxUrls(parseInt(e.target.value))} />
                        <span className="text-sm text-gray-600">{maxUrls}</span>
                    </div>
                   <div className="mb-2">
                        <label className="block text-gray-700 text-sm font-bold mb-2">Crawl Depth</label>
                       <input type="range" className="form-range w-full" min={1} max={3} value={crawlDepth} onChange={(e) => setCrawlDepth(parseInt(e.target.value))} />
                        <span className="text-sm text-gray-600">{crawlDepth}</span>
                    </div>
                    <button
                        className={`bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline ${isProcessing ? 'opacity-50 cursor-not-allowed' : ''}`}
                        onClick={handleProcessUrls}
                        disabled={isProcessing}
                    >
                        {isProcessing ? 'Processing...' : 'Process URLs'}
                    </button>
                     {scrapedDataOutput && (
                         <div className="mt-4">
                            <label className="block text-gray-700 text-sm font-bold mb-2">Scraped Data</label>
                                <pre className="border border-gray-300 rounded-md bg-gray-50 p-2 overflow-auto max-h-48 whitespace-pre-wrap">
                                    {scrapedDataOutput}
                                 </pre>
                         </div>
                        )}
                      {screenshotOutput && (
                        <div className="mt-4">
                            <label className="block text-gray-700 text-sm font-bold mb-2">Screenshot</label>
                             <img src={screenshotOutput} alt="Screenshot" className="rounded-lg shadow-lg max-h-96" />
                         </div>
                        )}
                   {!screenshotOutput && actionRadio === 'Capture image' && (
                        <div className="mt-4">
                            <label className="block text-gray-700 text-sm font-bold mb-2">Screenshot</label>
                            <div className="bg-gray-200 border-2 border-dashed rounded-xl w-48 h-48 flex items-center justify-center">
                                    <span className="text-gray-500">No image</span>
                                </div>
                        </div>
                        )}
                </div>


                <div className="bg-white rounded-lg shadow-md p-4 flex-1">
                    <h2 className="text-xl font-semibold mb-4 text-gray-700">Monitoring</h2>
                    <div className="mb-2">
                        <label className="block text-gray-700 text-sm font-bold mb-2">Enter URLs to Monitor (separated by newline)</label>
                         <textarea
                             className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                            value={monitorUrlInput}
                            onChange={(e) => setMonitorUrlInput(e.target.value)}
                        />
                    </div>
                    <div className="mb-2">
                        <label className="block text-gray-700 text-sm font-bold mb-2">Monitoring Interval (seconds)</label>
                         <input type="range" className="form-range w-full" min={1} max={3600} value={intervalInput} onChange={(e) => setIntervalInput(parseInt(e.target.value))} />
                        <span className="text-sm text-gray-600">{intervalInput}</span>
                    </div>
                    <div className="flex space-x-4 mb-4">
                        <button
                            className={`bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline ${isMonitoring ? 'opacity-50 cursor-not-allowed' : ''}`}
                            onClick={handleStartMonitoring}
                            disabled={isMonitoring}
                        >
                            Start Monitoring
                        </button>
                        <button
                           className={`bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline ${!isMonitoring ? 'opacity-50 cursor-not-allowed' : ''}`}
                             onClick={handleStopMonitoring}
                            disabled={!isMonitoring}
                        >
                             Stop Monitoring
                        </button>
                    </div>

                      {changeOutput && (
                        <div className="mb-4">
                             <label className="block text-gray-700 text-sm font-bold mb-2">Monitoring Changes</label>
                            <pre className="border border-gray-300 rounded-md bg-gray-50 p-2 overflow-auto max-h-48 whitespace-pre-wrap">
                                {changeOutput}
                            </pre>
                         </div>
                       )}
                      {monitoringData.length > 0 && (
                             <div className="mb-4">
                            <label className="block text-gray-700 text-sm font-bold mb-2">Change History Graph</label>
                            <ResponsiveContainer width="100%" height={200}>
                                <LineChart data={monitoringData}>
                                    <CartesianGrid strokeDasharray="3 3" />
                                    <XAxis dataKey="time" />
                                    <YAxis />
                                    <Tooltip />
                                    <Legend />
                                    <Line type="monotone" dataKey="changes" stroke="#8884d8" />
                                </LineChart>
                             </ResponsiveContainer>
                          </div>
                      )}
                    <div className="mb-2">
                           <label className="block text-gray-700 text-sm font-bold mb-2">Monitoring Chat</label>
                          <div className="border rounded-md bg-gray-50 p-2 overflow-auto max-h-48 mb-2">
                                <ul className="space-y-2">
                                     {chatHistory.map((msg, index) => (
                                          <li key={index} className={msg.role === 'user' ? 'text-right' : 'text-left'}>
                                             <div className={`${msg.role === 'user' ? 'bg-indigo-100' : 'bg-gray-100'} inline-block rounded-md p-2`}>
                                                 <span className="font-bold text-gray-700">{msg.role === 'user' ? 'You' : 'System'}:</span> <span className="text-gray-800">{msg.content}</span>
                                            </div>
                                        </li>
                                    ))}
                               </ul>
                           </div>
                         <input
                            type="text"
                            placeholder="Type command"
                            className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
                            onKeyDown={(e) => {
                                if (e.key === 'Enter') {
                                     handleChatSubmit(e.target.value);
                                    (e.target as HTMLInputElement).value = '';
                                }
                            }}
                        />
                    </div>
                </div>
            </div>
        </div>
    );
};

export default App;