"use client";
import React, { useState, useEffect, useCallback } from 'react';
import { useEditorStore } from '@/stores/editor-store';
import { XIcon } from 'lucide-react';
import useFlowStore, { useFlowStoreActions } from '@/stores/flow-store';
import { Node } from '@xyflow/react';

import Form from '@rjsf/core';
import { RJSFSchema, UiSchema, getTemplate, TemplatesType, FieldHelpProps } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';
import { ObjectFieldTemplateProps, FieldTemplateProps, WidgetProps } from '@rjsf/utils';
import { FormProps } from '@rjsf/core';

import { useNodesStore } from '@/stores/nodes-store';

// Types & Interfaces
interface ServiceFormData {
    version: string;
    name: string;
    summary: string;
    description: string;
}

interface NodeData extends ServiceFormData {
    [key: string]: any;
}

type ServiceNode = Node<NodeData>;

const FORM_UI_SCHEMA: UiSchema<ServiceFormData> = {
    name: {
        'ui:description': 'The name of the service',
        'ui:help': 'Enter the name of your service'
    },
    version: {
        'ui:description': 'The version number (e.g., 1.0.0)',
        'ui:help': 'Format: MAJOR.MINOR.PATCH (e.g., 2.1.0)',
        'ui:errormessage': {
            pattern: 'Please enter a valid version number like 1.0.0'
        }
    },
    summary: {
        'ui:widget': 'textarea',
        'ui:description': 'A brief summary of the service',
        'ui:help': 'Provide a short summary that describes your service'
    },
    'ui:submitButtonOptions': { 
        norender: true 
    }
};

const BaseInputTemplate = (props: WidgetProps<ServiceFormData>) => {
    const { id, value, onChange, disabled, placeholder, label, required } = props;

    

    // const nodeConfiguration = getNodeConfiguration(props.schema.type);

    return (
        <input
            id={id}
            type="text"
            value={value || ''}
            onChange={(e) => onChange(e.target.value)}
            disabled={disabled}
            required={required}
            placeholder={placeholder || `Enter ${label?.toLowerCase()}`}
            className="
                w-full
                px-3
                py-2
                bg-white
                border-2
                border-gray-200
                rounded-md
                shadow-sm
                focus:outline-none
                focus:ring-2
                focus:ring-indigo-500/20
                focus:border-indigo-500
                disabled:bg-gray-50
                disabled:cursor-not-allowed
                placeholder:text-gray-400
                text-gray-900
                transition-colors
                duration-200
            "
        />
    );
};

const BaseTextareaWidget = (props: WidgetProps<ServiceFormData>) => {
    const { id, value, onChange, disabled, placeholder, label, required } = props;
    return (
        <textarea
            id={id}
            value={value || ''}
            onChange={(e) => onChange(e.target.value)}
            disabled={disabled}
            required={required}
            placeholder={placeholder || `Enter ${label?.toLowerCase()}`}
            rows={4}
            className="
                w-full
                px-3
                py-2
                bg-white
                border-2
                border-gray-200
                rounded-md
                shadow-sm
                focus:outline-none
                focus:ring-2
                focus:ring-indigo-500/20
                focus:border-indigo-500
                disabled:bg-gray-50
                disabled:cursor-not-allowed
                placeholder:text-gray-400
                text-gray-900
                transition-colors
                duration-200
                resize-none
            "
        />
    );
};

const FileWidget = (props: WidgetProps<ServiceFormData>) => {
    const { id, value, onChange, disabled, label, required } = props;
    
    const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        const file = e.target.files?.[0];
        if (file) {
            const reader = new FileReader();
            reader.onload = () => {
                onChange(reader.result as string);
            };
            reader.readAsDataURL(file);
        }
    };

    const handleRemove = () => {
        onChange(null);
    };

    return (
        <div className="space-y-3">
            <input
                id={id}
                type="file"
                accept="image/*"
                onChange={handleFileChange}
                disabled={disabled}
                required={required && !value}
                className="
                    block
                    w-full
                    text-sm
                    text-gray-500
                    file:mr-4
                    file:py-2
                    file:px-4
                    file:rounded-lg
                    file:border-0
                    file:text-sm
                    file:font-medium
                    file:bg-indigo-50
                    file:text-indigo-700
                    hover:file:bg-indigo-100
                    file:cursor-pointer
                    cursor-pointer
                "
            />
            {value && (
                <div className="relative inline-block">
                    <img
                        src={value}
                        alt={`${label} preview`}
                        className="max-w-xs max-h-32 object-cover rounded-md border border-gray-200"
                    />
                    <button
                        type="button"
                        onClick={handleRemove}
                        className="
                            absolute
                            top-1
                            right-1
                            bg-red-500
                            text-white
                            rounded-full
                            w-6
                            h-6
                            flex
                            items-center
                            justify-center
                            text-xs
                            hover:bg-red-600
                            transition-colors
                        "
                    >
                        ×
                    </button>
                </div>
            )}
        </div>
    );
};

const FieldHelpTemplate = ({ help, idSchema }: FieldHelpProps<ServiceFormData>) => (
    <div id={`${idSchema.$id}__help`} className="help-block">
        {help}
    </div>
);

const templates: Partial<TemplatesType<ServiceFormData>> = {
    BaseInputTemplate,
    FieldTemplate: (props: FieldTemplateProps<ServiceFormData>) => {
        const { id, label, help, required, children, errors, rawErrors, schema } = props;
        const hasError = rawErrors && rawErrors.length > 0;
        return (
            <div className="mb-6">
                <label 
                    htmlFor={id} 
                    className={`block text-base font-medium mb-2 ${hasError ? 'text-red-600' : 'text-gray-700'}`}
                >
                    {label}
                    {required && <span className="text-red-500 ml-1">*</span>}
                </label>
                {children}
                {hasError && (
                    <div className="mt-1 text-sm text-red-600">{errors}</div>
                )}
                {(help || schema.description) && (
                    <div className="mt-1 text-sm text-gray-500">{help || schema.description}</div>
                )}
            </div>
        );
    },
    ObjectFieldTemplate: (props: ObjectFieldTemplateProps<ServiceFormData>) => {
        const { properties } = props;
        return (
            <div className="space-y-6">
                {properties.map((prop) => prop.content)}
            </div>
        );
    },
    FieldHelpTemplate
};

const generateUiSchema = (schema: RJSFSchema): UiSchema => {
    const uiSchema: UiSchema = {
        'ui:submitButtonOptions': { 
            norender: true 
        }
    };

    const processProperties = (properties: any, path: string = '') => {
        if (!properties) return;
        
        Object.keys(properties).forEach(key => {
            const property = properties[key];
            const fullKey = path ? `${path}.${key}` : key;
            
            if (property.format === 'data-url') {
                if (path) {
                    if (!uiSchema[path]) uiSchema[path] = {};
                    uiSchema[path][key] = { 'ui:widget': 'FileWidget' };
                } else {
                    uiSchema[key] = { 'ui:widget': 'FileWidget' };
                }
            } else if (property.type === 'object' && property.properties) {
                processProperties(property.properties, fullKey);
            }
        });
    };

    if (schema.properties) {
        processProperties(schema.properties);
    }

    return uiSchema;
};

const Editor = () => {
    const [initialNode, setInitialNode] = useState<ServiceNode | null>(null);
    const { selectedNode, setSelectedNode } = useEditorStore();
    const [schema, setSchema] = useState<RJSFSchema | null>(null);
    const [uiSchema, setUiSchema] = useState<UiSchema>({});
    const [nodeConfiguration, setNodeConfiguration] = useState<any>(null);
    const { updateNode } = useFlowStoreActions();
    const { getNodeConfiguration } = useNodesStore();


    useEffect(() => {
        if(selectedNode) {
            setInitialNode(selectedNode);
            const configuration = getNodeConfiguration(selectedNode?.type);
            if(configuration) {
                setNodeConfiguration(configuration);
                const schema = configuration.editor.schema;
                setSchema(schema);
                setUiSchema(generateUiSchema(schema));
            }
        }
    }, [selectedNode]);

    const handleClose = () => {
        setSelectedNode(null);
        if (initialNode) {
            updateNode({ ...initialNode, data: { ...initialNode.data } });
        }
    };

    const handleSubmit: FormProps<ServiceFormData>['onSubmit'] = ({ formData }) => {
        setSelectedNode(null);
        useFlowStore.getState().reactFlowInstance?.fitView({ duration: 1000 });
    };

    const handleChange: FormProps<ServiceFormData>['onChange'] = ({ formData }) => {
        if (selectedNode) {
            updateNode({
                ...selectedNode,
                data: {
                    ...selectedNode.data,
                    ...formData
                }
            });
        }
    };

    const log = (type: string) => console.log.bind(console, type);

    if(!schema) {
        return;
    }

    return (
        <div
            className={`h-full bg-white shadow-xl border-l border-gray-200 transition-all duration-300 ease-in-out transform flex flex-col ${selectedNode ? 'w-1/3 p-6' : 'w-0 p-0'} overflow-hidden`}
        >
            {selectedNode && (
                <>
                    <div className="flex items-center justify-between mb-4">
                        <div>
                            <h2 className="text-2xl font-semibold text-gray-900">
                                {nodeConfiguration?.editor?.title || 'Edit Node'}
                            </h2>
                            <p className="mt-1 text-sm text-gray-500">
                                {nodeConfiguration?.editor?.subtitle || 'Update the node details below.'}
                            </p>
                        </div>
                        <button 
                            onClick={handleClose} 
                            className="
                                p-2 
                                rounded-lg 
                                text-gray-500 
                                hover:text-gray-700 
                                hover:bg-gray-100 
                                focus:outline-none 
                                focus:ring-2 
                                focus:ring-indigo-500 
                                focus:ring-offset-2
                                transition-colors
                                duration-200
                            "
                        >
                            <XIcon className="h-5 w-5" />
                        </button>
                    </div>

                    <div className="flex-1 overflow-y-auto pr-6">
                        <Form
                            schema={schema}
                            validator={validator as any}
                            onChange={handleChange}
                            onSubmit={handleSubmit}
                            onError={log('errors')}
                            uiSchema={uiSchema}
                            formData={selectedNode.data}
                            templates={{
                                ...templates,
                                FieldHelpTemplate
                            }}
                            widgets={{
                                TextWidget: BaseInputTemplate,
                                TextareaWidget: BaseTextareaWidget,
                                FileWidget: FileWidget
                            }}
                        />
                    </div>

                    <div className="mt-8 pt-6 border-t border-gray-200 flex justify-end space-x-3">
                        <button
                            type="button"
                            onClick={handleClose}
                            className="
                                px-4 
                                py-2 
                                border 
                                border-gray-300 
                                rounded-lg 
                                text-sm 
                                font-medium 
                                text-gray-700 
                                bg-white 
                                hover:bg-gray-50 
                                focus:outline-none 
                                focus:ring-2 
                                focus:ring-offset-2 
                                focus:ring-indigo-500
                                transition-colors
                                duration-200
                            "
                        >
                            Cancel
                        </button>
                        <button
                            type="submit"
                            onClick={() => document.querySelector('form')?.requestSubmit()}
                            className="
                                px-4 
                                py-2 
                                border 
                                border-transparent 
                                rounded-lg 
                                text-sm 
                                font-medium 
                                text-white 
                                bg-indigo-600 
                                hover:bg-indigo-700 
                                focus:outline-none 
                                focus:ring-2 
                                focus:ring-offset-2 
                                focus:ring-indigo-500
                                transition-colors
                                duration-200
                            "
                        >
                            Save Changes
                        </button>
                    </div>
                </>
            )}
        </div>
    );
};

export default Editor;