import { useEffect, useState, useRef } from 'react';
import { Column } from 'primereact/column';
import { FilterMatchMode } from 'primereact/api';
import TableGroupHeader from '../shared/components/_V1/TableGroupHeader';
import TableGroup from '../shared/components/_V1/TableGroup';
import { TSizeOptionValue } from '../types/DataTable.types';
import { api } from '../services/api';
import { Button } from 'primereact/button';
import { Dialog } from 'primereact/dialog';
import { InputText } from 'primereact/inputtext';
import { Dropdown } from 'primereact/dropdown';
import { ProgressSpinner } from 'primereact/progressspinner';
import ChatGptModal from './ChatGPTModal';
import { Toast } from 'primereact/toast';

export default function CanvasEndpoints() {
    const [endpoints, setEndpoints] = useState<any[]>([]);
    const [filters, setFilters] = useState<any>(null);
    const [globalFilterValue, setGlobalFilterValue] = useState('');
    const [showCreateModal, setShowCreateModal] = useState(false);
    const [newEndpoint, setNewEndpoint] = useState({ name: '', method: '', path: '', description: '' });
    const sizeOptions: { label: string; value: TSizeOptionValue }[] = [
        { label: 'Small', value: 'small' },
        { label: 'Normal', value: 'normal' },
        { label: 'Large', value: 'large' },
    ];
    const [size, setSize] = useState<TSizeOptionValue>(sizeOptions[0].value);
    const [showCallModal, setShowCallModal] = useState(false);
    const [callModalData, setCallModalData] = useState<any[]>([]);
    const [callModalColumns, setCallModalColumns] = useState<string[]>([]);
    const [callModalLoading, setCallModalLoading] = useState(false);
    const [callEndpoint, setCallEndpoint] = useState<any>(null);
    const [callModalFilters, setCallModalFilters] = useState<any>(null);
    const [callModalGlobalFilterValue, setCallModalGlobalFilterValue] = useState('');
    const [callModalSize, setCallModalSize] = useState<TSizeOptionValue>(sizeOptions[0].value);
    const [callModalFirst, setCallModalFirst] = useState(0);
    const [callModalRows, setCallModalRows] = useState(10);
    const [showChatGptModal, setShowChatGptModal] = useState(false);
    const [chatPrompt, setChatPrompt] = useState('');
    const [chatMessages, setChatMessages] = useState<{ role: 'user' | 'assistant'; content: string }[]>([]);
    const [chatLoading, setChatLoading] = useState(false);
    const [chatError, setChatError] = useState<string | null>(null);
    const toast = useRef(null);

    useEffect(() => {
        initFilters();
        fetchEndpoints();
    }, []);

    const fetchEndpoints = async () => {
        try {
            const response = await api('get', '/api/v1/canvas-api/endpoints');
            setEndpoints(response.data);
        } catch (error) {
            console.error('Failed to fetch endpoints:', error);
        }
    };

    const initFilters = () => {
        setFilters({
            global: { value: null, matchMode: FilterMatchMode.CONTAINS },
        });
        setGlobalFilterValue('');
    };

    const clearFilter = () => {
        initFilters();
    };

    const onGlobalFilterChange = (e: { target: { value: any } }) => {
        const value = e.target.value;
        let _filters = { ...filters };
        _filters['global'].value = value;
        setFilters(_filters);
        setGlobalFilterValue(value);
    };

    // Utility to ensure path never starts with /api/v1
    function sanitizeCanvasPath(path: string) {
        return path.replace(/^\/api\/v1/, '');
    }

    const handleCreateEndpoint = async () => {
        try {
            const sanitizedEndpoint = { ...newEndpoint, path: sanitizeCanvasPath(newEndpoint.path) };
            await api('post', '/api/v1/canvas-api/endpoints', sanitizedEndpoint);
            setShowCreateModal(false);
            setNewEndpoint({ name: '', method: '', path: '', description: '' });
            fetchEndpoints();
        } catch (error) {
            console.error('Failed to create endpoint:', error);
        }
    };

    const handleCallEndpoint = async (endpoint: any) => {
        setShowCallModal(true);
        setCallModalLoading(true);
        setCallEndpoint(endpoint);
        try {
            const res = await api('post', '/api/v1/canvas-api/proxy-external', {
                path: endpoint.path,
                method: endpoint.method || 'GET',
            });
            let data = res.data;
            if (!Array.isArray(data)) data = [data];
            setCallModalData(data);
            setCallModalColumns(data.length > 0 ? Object.keys(data[0]) : []);
        } catch (error) {
            setCallModalData([]);
            setCallModalColumns([]);
        } finally {
            setCallModalLoading(false);
        }
    };

    const initCallModalFilters = () => {
        setCallModalFilters({
            global: { value: null, matchMode: FilterMatchMode.CONTAINS },
        });
        setCallModalGlobalFilterValue('');
    };

    const clearCallModalFilter = () => {
        initCallModalFilters();
    };

    const onCallModalGlobalFilterChange = (e: { target: { value: any } }) => {
        const value = e.target.value;
        let _filters = { ...callModalFilters };
        _filters['global'].value = value;
        setCallModalFilters(_filters);
        setCallModalGlobalFilterValue(value);
    };

    const handleChatPromptSend = async () => {
        if (!chatPrompt.trim()) return;
        setChatLoading(true);
        setChatError(null);
        setChatMessages(prev => [...prev, { role: 'user', content: chatPrompt }]);
        try {
            const formattedRequest = {
                data: chatPrompt,
            };
            const response = await api(
                'post',
                '/api/v1/canvas-api/chatgpt/completions',
                formattedRequest,
                undefined,
                'json',
                60,
                true
            );
            const data = response.data;
            let isEndpointJson = false;
            if (data && data.responseText) {
                let parsed;
                try {
                    parsed = typeof data.responseText === 'string' ? JSON.parse(data.responseText) : data.responseText;
                } catch (e) {
                    parsed = null;
                }
                if (parsed && parsed.name && parsed.method && parsed.path) {
                    // Auto-create endpoint
                    const sanitizedParsed = { ...parsed, path: sanitizeCanvasPath(parsed.path) };
                    await api('post', '/api/v1/canvas-api/endpoints', sanitizedParsed);
                    fetchEndpoints();
                    isEndpointJson = true;
                    if (toast.current) {
                        toast.current.show({ severity: 'success', summary: 'Endpoint Created', detail: `Endpoint "${parsed.name}" created successfully!` });
                    }
                }
            }
            if (!isEndpointJson) {
                setChatMessages(prev => [...prev, { role: 'assistant', content: typeof data.responseText === 'string' ? data.responseText : JSON.stringify(data.responseText, null, 2) }]);
            }
        } catch (err) {
            setChatError('Failed to get response from server.');
            setChatMessages(prev => [...prev, { role: 'assistant', content: 'Failed to get response from server.' }]);
        } finally {
            setChatLoading(false);
            setChatPrompt('');
        }
    };

    const handleChatPromptKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
        if (e.key === 'Enter' && !e.shiftKey) {
            e.preventDefault();
            handleChatPromptSend();
        }
    };

    const handleDeleteEndpoint = async (endpoint: any) => {
        try {
            await api('delete', `/api/v1/canvas-api/endpoints/${endpoint.id}`);
            fetchEndpoints();
            if (toast.current) {
                toast.current.show({ severity: 'success', summary: 'Endpoint Deleted', detail: `Endpoint "${endpoint.name}" deleted successfully!` });
            }
        } catch (error) {
            if (toast.current) {
                toast.current.show({ severity: 'error', summary: 'Delete Failed', detail: 'Failed to delete endpoint.' });
            }
        }
    };

    const renderHeader = () => (
        <TableGroupHeader
            size={size}
            setSize={setSize}
            sizeOptions={sizeOptions}
            globalFilterValue={globalFilterValue}
            onGlobalFilterChange={onGlobalFilterChange}
            onRefresh={fetchEndpoints}
            clearFilter={clearFilter}
            extraButtonsTemplate={() => (
                <div className="flex gap-2">
                    <Button
                        label="Create Endpoint"
                        icon="pi pi-plus"
                        onClick={() => setShowCreateModal(true)}
                    />
                    <Button
                        label="Ask ChatGPT"
                        icon="pi pi-comments"
                        onClick={() => setShowChatGptModal(true)}
                        className="p-button-primary"
                    />
                </div>
            )}
        />
    );

    const renderCallButton = (rowData: any) => (
        <div className="flex gap-2">
            <Button label="Call" icon="pi pi-play" onClick={() => handleCallEndpoint(rowData)} />
            <Button label="Delete" icon="pi pi-trash" className="p-button-danger" onClick={() => handleDeleteEndpoint(rowData)} />
        </div>
    );

    const renderCallModalHeader = () => (
        <TableGroupHeader
            size={callModalSize}
            setSize={setCallModalSize}
            sizeOptions={sizeOptions}
            globalFilterValue={callModalGlobalFilterValue}
            onGlobalFilterChange={onCallModalGlobalFilterChange}
            onRefresh={() => handleCallEndpoint(callEndpoint)}
            clearFilter={clearCallModalFilter}
        />
    );

    return (
        <div className='w-full h-full p-6'>
            <h2 className='text-xl font-semibold mb-4'>Canvas Endpoints</h2>
            <Toast ref={toast} position="bottom-right" />
            <TableGroup
                body={endpoints}
                size={size}
                header={renderHeader}
                filters={filters}
                rows={10}
                paginator
                showGridlines={true}
                removableSort={true}
                dragSelection={false}
                emptyMessage='No endpoints found.'
            >
                <Column field='id' header='ID' sortable filter style={{ width: '10%' }} />
                <Column field='name' header='Name' sortable filter style={{ width: '20%' }} />
                <Column field='method' header='Method' sortable filter style={{ width: '10%' }} />
                <Column field='path' header='Path' sortable filter style={{ width: '40%' }} />
                <Column header='Action' body={renderCallButton} style={{ width: '20%' }} />
            </TableGroup>

            <Dialog
                visible={showCreateModal}
                onHide={() => setShowCreateModal(false)}
                header="Create New Endpoint"
                footer={
                    <div>
                        <Button label="Cancel" icon="pi pi-times" onClick={() => setShowCreateModal(false)} className="p-button-text" />
                        <Button label="Create" icon="pi pi-check" onClick={handleCreateEndpoint} autoFocus disabled={!(newEndpoint.name && newEndpoint.method && newEndpoint.path)} />
                    </div>
                }
            >
                <div className="p-fluid">
                    <div className="p-field">
                        <label htmlFor="name">Name</label>
                        <InputText id="name" value={newEndpoint.name} onChange={(e) => setNewEndpoint({ ...newEndpoint, name: e.target.value })} />
                    </div>
                    <div className="p-field">
                        <label htmlFor="method">Method</label>
                        <Dropdown
                            id="method"
                            value={newEndpoint.method}
                            options={[
                                { label: 'GET', value: 'GET' },
                                { label: 'POST', value: 'POST' },
                                { label: 'PUT', value: 'PUT' },
                                { label: 'DELETE', value: 'DELETE' }
                            ]}
                            onChange={(e) => setNewEndpoint({ ...newEndpoint, method: e.value })}
                            placeholder="Select a method"
                        />
                    </div>
                    <div className="p-field">
                        <label htmlFor="path">Path</label>
                        <InputText id="path" value={newEndpoint.path} onChange={(e) => setNewEndpoint({ ...newEndpoint, path: e.target.value })} />
                    </div>
                    <div className="p-field">
                        <label htmlFor="description">Description</label>
                        <InputText id="description" value={newEndpoint.description} onChange={(e) => setNewEndpoint({ ...newEndpoint, description: e.target.value })} />
                    </div>
                </div>
            </Dialog>

            <Dialog
                visible={showCallModal}
                onHide={() => setShowCallModal(false)}
                header={callEndpoint ? `Response for ${callEndpoint.name}` : 'Endpoint Response'}
                style={{ width: '96vw', maxWidth: 1800, minHeight: 600 }}
                modal
            >
                {callModalLoading ? (
                    <div className="flex justify-center items-center" style={{ minHeight: 200 }}>
                        <ProgressSpinner />
                    </div>
                ) : callModalData.length > 0 ? (
                    <div style={{ display: 'flex', flexDirection: 'column', height: '70vh' }}>
                        <div style={{ flex: 1, overflow: 'auto', maxWidth: '100%' }}>
                            <TableGroup
                                body={callModalData.slice(callModalFirst, callModalFirst + callModalRows)}
                                size={callModalSize}
                                header={renderCallModalHeader}
                                filters={callModalFilters}
                                rows={callModalRows}
                                paginator={false}
                                showGridlines={true}
                                removableSort={true}
                                dragSelection={false}
                                emptyMessage='No data found.'
                            >
                                {callModalColumns.map((col) => (
                                    <Column
                                        key={col}
                                        field={col}
                                        header={col}
                                        sortable
                                        filter
                                        body={rowData => {
                                            const value = rowData[col];
                                            if (typeof value === 'object' && value !== null) {
                                                return <span style={{ fontFamily: 'monospace', fontSize: 12 }}>{JSON.stringify(value)}</span>;
                                            }
                                            return value;
                                        }}
                                    />
                                ))}
                            </TableGroup>
                        </div>
                        <div style={{ position: 'sticky', bottom: 0, background: '#fff', padding: '8px 0 0 0', zIndex: 2, borderTop: '1px solid #eee' }}>
                            <div style={{ width: '100%' }}>
                                <span style={{ float: 'right' }}>
                                    <span style={{ marginRight: 16 }}>
                                        Showing {callModalFirst + 1} to {Math.min(callModalFirst + callModalRows, callModalData.length)} of {callModalData.length} entries
                                    </span>
                                    <select
                                        value={callModalRows}
                                        onChange={e => setCallModalRows(Number(e.target.value))}
                                        style={{ marginRight: 8 }}
                                    >
                                        {[10, 25, 50].map(opt => (
                                            <option key={opt} value={opt}>{opt}</option>
                                        ))}
                                    </select>
                                    <button onClick={() => setCallModalFirst(0)} disabled={callModalFirst === 0}>{'<<'}</button>
                                    <button onClick={() => setCallModalFirst(Math.max(0, callModalFirst - callModalRows))} disabled={callModalFirst === 0}>{'<'}</button>
                                    <span style={{ margin: '0 8px' }}>{Math.floor(callModalFirst / callModalRows) + 1}</span>
                                    <button onClick={() => setCallModalFirst(Math.min(callModalFirst + callModalRows, callModalData.length - callModalRows))} disabled={callModalFirst + callModalRows >= callModalData.length}>{'>'}</button>
                                    <button onClick={() => setCallModalFirst(Math.max(0, callModalData.length - callModalRows))} disabled={callModalFirst + callModalRows >= callModalData.length}>{'>>'}</button>
                                </span>
                            </div>
                        </div>
                    </div>
                ) : (
                    <div>No data found or error.</div>
                )}
            </Dialog>

            <Dialog
                visible={showChatGptModal}
                onHide={() => setShowChatGptModal(false)}
                header="ChatGPT Assistant"
                style={{ width: '50vw' }}
            >
                <div className="flex flex-col h-[60vh]">
                    <div className="flex-1 overflow-auto mb-4 p-2 bg-gray-50 rounded">
                        {chatMessages.length === 0 && <div className="text-gray-400 text-center mt-8">Start a conversation with ChatGPT...</div>}
                        {chatMessages.map((msg, idx) => (
                            <div key={idx} className={`my-2 p-2 rounded-lg max-w-[80%] ${msg.role === 'user' ? 'bg-blue-100 ml-auto' : 'bg-gray-200'}`}>
                                <span>{msg.content}</span>
                            </div>
                        ))}
                    </div>
                    <div className="flex gap-2 mt-auto">
                        <input
                            type="text"
                            className="flex-1 p-2 border rounded"
                            placeholder="Type your message..."
                            value={chatPrompt}
                            onChange={e => setChatPrompt(e.target.value)}
                            onKeyDown={handleChatPromptKeyDown}
                            disabled={chatLoading}
                        />
                        <Button
                            icon="pi pi-send"
                            onClick={handleChatPromptSend}
                            loading={chatLoading}
                            disabled={!chatPrompt.trim() || chatLoading}
                        />
                    </div>
                    {chatError && <div className="text-red-500 mt-2">{chatError}</div>}
                </div>
            </Dialog>
        </div>
    );
} 