import React, { useState } from 'react';
import { Form, Formik } from 'formik';
import { object, string } from 'yup';
import { ServerContext } from '@/state/server';
import { saveFileContents } from '../api/server/files';
import { useFlashKey } from '../useFlash';
import { Dialog } from '@/components/elements/dialog';
import { Button } from '@/components/elements/button/index';
import Field from '@/components/elements/Field';
import Code from '@/components/elements/Code';
import Label from '@/components/elements/Label';
import Select from '@/components/elements/Select';
import { getTemplates, type FileTemplate } from '../main/components/SettingsDialog';

interface Props {
    visible: boolean;
    onDismiss: () => void;
    directories: string[];
    onFileCreated: () => Promise<void>;
}

const CreateFileModal: React.FC<Props> = ({ visible, onDismiss, directories, onFileCreated }) => {
    const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
    const { clearAndAddHttpError } = useFlashKey('better-files');
    const [selectedTemplate, setSelectedTemplate] = useState<FileTemplate | null>(null);
    const templates = getTemplates();
    const targetDirectories = Array.from(
        new Set(
            (directories.length ? directories : ['/']).map((path) => (path.startsWith('/') ? path : `/${path}`))
        )
    );

    const handleTemplateSelect = (
        templateId: string,
        setFieldValue: (field: string, value: string) => void
    ) => {
        if (!templateId) {
            setSelectedTemplate(null);
            return;
        }
        const template = templates.find(t => t.id === templateId) || null;
        setSelectedTemplate(template);
        if (template) {
            setFieldValue('name', template.filename);
        }
    };

    return (
        <Dialog
            open={visible}
            onClose={() => { onDismiss(); setSelectedTemplate(null); }}
            title='Create New File'
        >
            <div onMouseDown={e => e.stopPropagation()} onClick={e => e.stopPropagation()}>
                <Formik
                    initialValues={{
                        name: '',
                        directory: targetDirectories.length === 1 ? targetDirectories[0] : '',
                    }}
                    validationSchema={object().shape({
                        name: string().required('A file name is required'),
                    })}
                    onSubmit={async (values, { setSubmitting }) => {
                        try {
                            const customDirectory = values.directory?.trim();
                            const hasSingleTarget = targetDirectories.length === 1;
                            const targetList = hasSingleTarget ? [customDirectory || targetDirectories[0]] : targetDirectories;
                            const content = selectedTemplate?.content ?? '';
                            for (const rawDir of targetList) {
                                const directory = rawDir.startsWith('/') ? rawDir : `/${rawDir}`;
                                const filePath = directory === '/' ? '/' + values.name : directory + '/' + values.name;
                                await saveFileContents(uuid, filePath, content);
                            }
                            await onFileCreated();
                            setSelectedTemplate(null);
                            onDismiss();
                        } catch (error) {
                            clearAndAddHttpError(error as Error);
                        } finally {
                            setSubmitting(false);
                        }
                    }}
                >
                    {({ submitForm, values, setFieldValue, isSubmitting }) => (
                        <Form>
                            <div className='mb-4'>
                                <Label htmlFor='create-file-template'>Template</Label>
                                <Select
                                    id='create-file-template'
                                    value={selectedTemplate?.id ?? ''}
                                    onChange={(e) => handleTemplateSelect(e.target.value, setFieldValue)}
                                >
                                    <option value=''>Empty file</option>
                                    {templates.map(t => (
                                        <option key={t.id} value={t.id}>{t.name} ({t.filename})</option>
                                    ))}
                                </Select>
                            </div>

                            <Field
                                autoFocus
                                id='name'
                                name='name'
                                label='File Name'
                            />
                            {targetDirectories.length === 1 && (
                                <Field
                                    id='directory'
                                    name='directory'
                                    label='Directory (optional)'
                                    description='Override the destination directory for this file.'
                                    placeholder='/'
                                />
                            )}

                            {selectedTemplate && (
                                <div className='mt-3 rounded bg-neutral-800 border border-neutral-700 overflow-hidden'>
                                    <div className='px-3 py-1.5 border-b border-neutral-700 flex items-center justify-between'>
                                        <span className='text-xs text-neutral-500'>Preview</span>
                                    </div>
                                    <pre className='p-3 text-xs text-neutral-300 font-mono overflow-auto max-h-32 m-0'>
                                        {selectedTemplate.content || '(empty)'}
                                    </pre>
                                </div>
                            )}

                            {targetDirectories.length === 1 ? (
                                <p className='mt-2 text-sm text-neutral-400'>
                                    Will be created at:{' '}
                                    <Code>
                                        {(values.directory?.trim()
                                            ? values.directory.trim().startsWith('/')
                                                ? values.directory.trim()
                                                : '/' + values.directory.trim()
                                            : targetDirectories[0]) || '/'}
                                        {values.name ? '/' + values.name : ''}
                                    </Code>
                                </p>
                            ) : (
                                <p className='mt-2 text-sm text-neutral-400'>
                                    Will be created in <Code>{targetDirectories.length}</Code> directories.
                                </p>
                            )}
                            <Dialog.Footer>
                                <Button.Text onClick={() => { onDismiss(); setSelectedTemplate(null); }}>
                                    Cancel
                                </Button.Text>
                                <Button onClick={submitForm} disabled={isSubmitting}>
                                    Create File
                                </Button>
                            </Dialog.Footer>
                        </Form>
                    )}
                </Formik>
            </div>
        </Dialog>
    );
};

export default CreateFileModal;
