import { useEffect, useState } from "preact/hooks";
import { Trash2, Check } from "lucide-preact";
import { useBool } from "@common/hooks/useBool";
import { useInputState } from "@common/hooks/useInputState";
import { Modal } from "@common/components/Modal";
import clsx from "clsx";
import styles from "../../assets/manage-workers-modal.module.css";
import ui from "@common/assets/ui.module.css";
import { useHordeState } from "../../contexts/state";
import { deleteWorker, fetchWorker, updateWorker, type WorkerData, type WorkerEdit } from "../../utils/api";

interface Props {
    open: boolean;
    onClose: () => void;
}

interface WorkerCard {
    data: WorkerData;
    edit: WorkerEdit;
    saving: boolean;
    saved: boolean;
    deleting: boolean;
    confirmDelete: boolean;
}

export const ManageWorkersModal = ({ open, onClose }: Props) => {
    const { state, dispatch } = useHordeState();
    const { user, apiKey } = state;

    const [workers, setWorkers] = useState<WorkerCard[]>([]);
    const [error, setError] = useState<string | null>(null);
    const loading = useBool(false);

    useEffect(() => {
        if (!open || !user?.worker_ids || !apiKey || !user) return;
        let cancelled = false;

        loading.setTrue();
        setError(null);
        Promise.all(user.worker_ids.map(id => fetchWorker(id, apiKey)))
            .then(details => {
                if (cancelled) return;
                const sorted = details.sort((a, b) => {
                    if (a.online !== b.online) return a.online ? -1 : 1;
                    return a.name.localeCompare(b.name);
                });
                setWorkers(sorted.map(w => ({
                    data: w,
                    edit: { name: w.name, info: w.info ?? '', maintenance: w.maintenance_mode },
                    saving: false,
                    saved: false,
                    deleting: false,
                    confirmDelete: false,
                })));
            })
            .catch(() => { if (!cancelled) setError('Failed to load workers'); })
            .finally(() => { if (!cancelled) loading.setFalse(); });

        return () => { cancelled = true; };
    }, [open, user?.worker_ids?.join(',')]);

    const setEdit = (id: string, patch: Partial<WorkerEdit>) => {
        setWorkers(prev => prev.map(w =>
            w.data.id === id
                ? { ...w, edit: { ...w.edit, ...patch }, saved: false }
                : w
        ));
    };

    const save = async (id: string) => {
        if (!apiKey) return;
        setWorkers(prev => prev.map(w => w.data.id === id ? { ...w, saving: true } : w));
        try {
            const worker = workers.find(w => w.data.id === id)!;
            const updated = await updateWorker(id, apiKey, worker.edit);
            setWorkers(prev => prev.map(w =>
                w.data.id === id
                    ? {
                        ...w, data: {
                            ...w.data,
                            ...updated,
                            maintenance_mode: Boolean(updated.maintenance),
                        }, saving: false, saved: true
                    }
                    : w
            ));
            setTimeout(() => {
                setWorkers(prev => prev.map(w =>
                    w.data.id === id ? { ...w, saved: false } : w
                ));
            }, 1500);
        } catch {
            setError('Failed to save worker');
            setWorkers(prev => prev.map(w =>
                w.data.id === id ? { ...w, saving: false } : w
            ));
        }
    };

    const startDelete = (id: string) => {
        setWorkers(prev => prev.map(w =>
            w.data.id === id ? { ...w, confirmDelete: true } : w
        ));
    };

    const cancelDelete = (id: string) => {
        setWorkers(prev => prev.map(w =>
            w.data.id === id ? { ...w, confirmDelete: false } : w
        ));
    };

    const confirmDelete = async (id: string) => {
        if (!apiKey || !user?.worker_ids) return;
        setWorkers(prev => prev.map(w =>
            w.data.id === id ? { ...w, deleting: true, confirmDelete: false } : w
        ));
        try {
            await deleteWorker(id, apiKey);
            setWorkers(prev => prev.filter(w => w.data.id !== id));
            dispatch({ type: 'SET_USER', user: { ...user!, worker_ids: user!.worker_ids.filter(i => i !== id) } });
        } catch {
            setError('Failed to delete worker');
            setWorkers(prev => prev.map(w =>
                w.data.id === id ? { ...w, deleting: false } : w
            ));
        }
    };

    const hasChanges = workers.some(w =>
        w.edit.name !== w.data.name ||
        w.edit.info !== (w.data.info ?? '') ||
        w.edit.maintenance !== w.data.maintenance_mode
    );

    const footer = (
        <div class={styles.footer}>
            <span class={styles.footerInfo}>
                {workers.length} worker{workers.length !== 1 ? 's' : ''}
                {hasChanges && ' · unsaved changes'}
            </span>
            {hasChanges && (
                <div class={styles.footerActions}>
                    <button class={ui.buttonPrimary} onClick={() => workers.forEach(w => { if (hasChangesForWorker(w)) save(w.data.id); })}>
                        Save All
                    </button>
                </div>
            )}
        </div>
    );

    const hasChangesForWorker = (w: WorkerCard) =>
        w.edit.name !== w.data.name ||
        w.edit.info !== (w.data.info ?? '') ||
        w.edit.maintenance !== w.data.maintenance_mode;

    return (
        <Modal open={open && Boolean(user)} onClose={onClose} title="Manage Workers" class={styles.modal} footer={footer}>
            {loading.value && <p class={styles.empty}>Loading workers…</p>}
            {error && <p class={styles.error}>{error}</p>}
            {!loading.value && !error && workers.length === 0 && (
                <p class={styles.empty}>No workers found.</p>
            )}
            {!loading.value && !error && workers.length > 0 && (
                <div class={styles.list}>
                    {workers.map(w => (
                        <div key={w.data.id} class={styles.workerCard}>
                            <div class={styles.workerHeader}>
                                <div class={styles.workerInfo}>
                                    <div class={styles.workerName}>{w.data.name}</div>
                                    <div class={styles.workerModels}>
                                        {w.data.models.slice(0, 3).join(', ')}
                                        {w.data.models.length > 3 && ` +${w.data.models.length - 3}`}
                                    </div>
                                </div>
                                <div class={styles.badges}>
                                    <span class={clsx(styles.badge, w.data.online ? styles.badgeOnline : styles.badgeOffline)}>
                                        {w.data.online ? 'online' : 'offline'}
                                    </span>
                                    {w.data.maintenance_mode && (
                                        <span class={styles.badgeMaintenance}>maint</span>
                                    )}
                                </div>
                            </div>

                            <div class={styles.fields}>
                                <div class={ui.formGroup}>
                                    <label class={ui.label}>Name</label>
                                    <input
                                        class={ui.input}
                                        value={w.edit.name}
                                        onInput={e => setEdit(w.data.id, { name: (e.target as HTMLInputElement).value })}
                                    />
                                </div>
                                <div class={ui.formGroup}>
                                    <label class={ui.label}>Info</label>
                                    <textarea
                                        class={ui.textarea}
                                        value={w.edit.info}
                                        onInput={e => setEdit(w.data.id, { info: (e.target as HTMLTextAreaElement).value })}
                                        rows={2}
                                    />
                                </div>
                            </div>

                            <div class={styles.actions}>
                                <label class={styles.checkboxLabel}>
                                    <input
                                        type="checkbox"
                                        checked={w.edit.maintenance}
                                        onChange={e => setEdit(w.data.id, { maintenance: (e.target as HTMLInputElement).checked })}
                                    />
                                    Maint.
                                </label>
                                {w.saved && (
                                    <span class={styles.toast}>
                                        <Check size={14} class={styles.toastIcon} />
                                        Saved
                                    </span>
                                )}
                                <div class={styles.spacer} />
                                {w.confirmDelete ? (
                                    <div class={styles.deleteConfirm}>
                                        <span>Really delete?</span>
                                        <button class={ui.confirmButton} onClick={() => confirmDelete(w.data.id)} disabled={w.deleting}>
                                            Yes
                                        </button>
                                        <button class={ui.cancelButton} onClick={() => cancelDelete(w.data.id)} disabled={w.deleting}>
                                            No
                                        </button>
                                    </div>
                                ) : (
                                    <>
                                        <button class={ui.buttonSecondary} onClick={() => save(w.data.id)} disabled={w.saving || !hasChangesForWorker(w)}>
                                            {w.saving ? 'Saving…' : 'Save'}
                                        </button>
                                        <button class={styles.deleteBtn} onClick={() => startDelete(w.data.id)} disabled={w.deleting}>
                                            <Trash2 size={16} />
                                            Delete
                                        </button>
                                    </>
                                )}
                            </div>
                        </div>
                    ))}
                </div>
            )}
        </Modal>
    );
};
