import React, {useCallback, useRef} from 'react';
import {usePage} from '@inertiajs/react';
import {registerPlugin, create as createFilePond} from 'filepond';
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
import FilePondPluginFileValidateSize from 'filepond-plugin-file-validate-size';
import 'filepond/dist/filepond.min.css';

interface FilePondUploaderProps {
    url?: string;
    name?: string;
    acceptedFileTypes?: string[];
    maxFileSize?: string;
    extraData?: () => Record<string, any>;
    onSuccess?: (data: any) => void;
    onError?: (err: any) => void;
    instantUpload?: boolean;
    onAddFile?: (file: File | null) => void;
}

registerPlugin(FilePondPluginFileValidateType, FilePondPluginFileValidateSize);

export default function FilePondUploader({
    url,
    name = 'file',
    acceptedFileTypes,
    maxFileSize,
    extraData,
    onSuccess,
    onError,
    instantUpload = true,
    onAddFile,
}: FilePondUploaderProps) {
    const pondRef = useRef<any>(null);

    // Safely grab token — page props may vary
    let token: string | undefined;
    try {
        const { auth } = usePage<{ auth: { user: any } }>().props;
        token = auth?.user?.token ?? auth?.user?.api_token ?? undefined;
    } catch (_) {
        token = undefined;
    }

    // Callback ref: runs when the DOM node mounts or unmounts
    const setInputRef = useCallback(
        (node: HTMLInputElement | null) => {
            // Tear down old instance when node unmounts
            if (!node) {
                if (pondRef.current) {
                    try { pondRef.current.destroy(); } catch (_) {}
                    pondRef.current = null;
                }
                return;
            }

            const commonOptions: any = {
                allowMultiple: false,
                acceptedFileTypes: acceptedFileTypes ?? [
                    'application/pdf',
                    'application/msword',
                    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                ],
                maxFileSize: maxFileSize ?? '50MB',
            };

            let pond: any;

            if (instantUpload === false) {
                pond = createFilePond(node, { ...commonOptions });
                pond.on('addfile', (error: any, fileItem: any) => {
                    if (error) { onError?.(error); return; }
                    onAddFile?.(fileItem.file ?? null);
                });
                pond.on('removefile', () => onAddFile?.(null));
            } else {
                pond = createFilePond(node, {
                    ...commonOptions,
                    server: {
                        process: (
                            fieldName: string,
                            file: File,
                            _metadata: any,
                            load: any,
                            error: any,
                            progress: any,
                            abort: any
                        ) => {
                            const form = new FormData();
                            form.append(fieldName, file, file.name);
                            const extra = extraData ? extraData() : {};
                            Object.keys(extra).forEach(k => form.append(k, extra[k]));

                            const xhr = new XMLHttpRequest();
                            xhr.open('POST', url ?? '', true);
                            if (token) xhr.setRequestHeader('Authorization', `Bearer ${token}`);
                            xhr.upload.onprogress = (e) => progress(true, e.loaded, e.total);

                            xhr.onload = () => {
                                if (xhr.status >= 200 && xhr.status < 300) {
                                    let res: any = {};
                                    try { res = JSON.parse(xhr.responseText); } catch (_) { res = xhr.responseText; }
                                    load(res?.result ?? res);
                                    onSuccess?.(res?.result ?? res);
                                } else {
                                    onError?.(xhr.responseText);
                                    error('Upload error');
                                }
                            };

                            xhr.onerror = () => {
                                onError?.({ message: 'Upload failed' });
                                error('Upload error');
                            };

                            xhr.send(form);

                            return { abort: () => { xhr.abort(); abort(); } };
                        },
                    },
                });
            }

            pondRef.current = pond;
        },
        // eslint-disable-next-line react-hooks/exhaustive-deps
        [url, token, instantUpload]
    );

    return <input ref={setInputRef} type="file" name={name} />;
}
