const { useDeferredValue, useEffect, useRef, useState, startTransition } = React;

const NAV_ITEMS = [
    { key: "dashboard", label: "Dashboard" },
    { key: "preset", label: "Preset Batteries" },
    { key: "custom", label: "Custom Batteries" },
    { key: "add", label: "Add Battery" },
    { key: "import", label: "Import Files" },
];

const DEFAULT_FORM = {
    name: "",
    battery_type: "Li-ion",
    num_cells: 48,
    base_voltage: 4.1,
    base_soh: 95,
    base_temp: 25,
    degradation_rate: 0.03,
    fault_probability: 0.1,
    capacity_ah: 100,
    max_charge_rate: 50,
    max_discharge_rate: 100,
    operating_temp_min: -10,
    operating_temp_max: 60,
    description: "Custom battery configuration",
};

function createOrUpdateChart(chartRef, canvasRef, config) {
    if (!canvasRef.current) {
        return;
    }

    if (!chartRef.current) {
        chartRef.current = new Chart(canvasRef.current.getContext("2d"), config);
        return;
    }

    chartRef.current.data = config.data;
    chartRef.current.options = config.options;
    chartRef.current.update("none");
}

function destroyChart(chartRef) {
    if (chartRef.current) {
        chartRef.current.destroy();
        chartRef.current = null;
    }
}

function formatMetric(value, suffix, digits) {
    if (value === null || value === undefined || Number.isNaN(Number(value))) {
        return "--";
    }

    return Number(value).toFixed(digits) + suffix;
}

function selectionKey(selection) {
    return selection ? selection.source + ":" + selection.id : "";
}

function selectPreferredBattery(catalog, preferred) {
    const combined = catalog.predefined.concat(catalog.custom);
    if (!combined.length) {
        return null;
    }

    if (!preferred) {
        return combined[0];
    }

    return combined.find(function findMatch(item) {
        return item.id === preferred.id && item.source === preferred.source;
    }) || combined[0];
}

function Sidebar({ activeSection, onSectionChange }) {
    return (
        <aside className="sidebar">
            <div className="brand-block">
                <p className="brand-kicker">IntelliBMS</p>
                <h1>Battery Monitor</h1>
                <p>Minimal monitoring workspace with light surfaces and live battery metrics.</p>
            </div>

            <nav className="nav-list">
                {NAV_ITEMS.map(function renderItem(item) {
                    return (
                        <button
                            key={item.key}
                            className={"nav-item" + (activeSection === item.key ? " active" : "")}
                            onClick={function handleClick() {
                                onSectionChange(item.key);
                            }}
                            type="button"
                        >
                            {item.label}
                        </button>
                    );
                })}
            </nav>
        </aside>
    );
}

function BatteryGrid({ items, onDelete, selected, title, onSelect }) {
    return (
        <section className="panel">
            <div className="panel-header">
                <h2>{title}</h2>
                <span>{items.length}</span>
            </div>
            <div className="selection-grid">
                {items.map(function renderBattery(item) {
                    const active = selected && item.id === selected.id && item.source === selected.source;
                    return (
                        <button
                            key={item.source + "-" + item.id}
                            className={"selection-card" + (active ? " active" : "")}
                            onClick={function handleSelect() {
                                onSelect(item);
                            }}
                            type="button"
                        >
                            <strong>{item.name}</strong>
                            <span>{item.battery_type}</span>
                            <p>{item.num_cells} cells / {formatMetric(item.base_voltage, "V", 2)}</p>
                            <p>SOH {formatMetric(item.base_soh, "%", 1)}</p>
                            {onDelete ? (
                                <span
                                    className="delete-link"
                                    onClick={function handleDelete(event) {
                                        event.stopPropagation();
                                        onDelete(item.id);
                                    }}
                                >
                                    Delete
                                </span>
                            ) : null}
                        </button>
                    );
                })}
            </div>
        </section>
    );
}

function BatteryForm({ form, notice, onChange, onSubmit, submitting }) {
    return (
        <section className="panel form-panel">
            <div className="panel-header">
                <h2>Add Battery</h2>
                <span>Minimal form</span>
            </div>
            {notice ? <div className="notice inline">{notice}</div> : null}
            <form className="stack" onSubmit={onSubmit}>
                <div className="field-grid">
                    <label>
                        <span>Name</span>
                        <input required value={form.name} onChange={function (event) { onChange("name", event.target.value); }} />
                    </label>
                    <label>
                        <span>Type</span>
                        <input value={form.battery_type} onChange={function (event) { onChange("battery_type", event.target.value); }} />
                    </label>
                    <label>
                        <span>Cells</span>
                        <input min="1" type="number" value={form.num_cells} onChange={function (event) { onChange("num_cells", Number(event.target.value)); }} />
                    </label>
                    <label>
                        <span>Base Voltage</span>
                        <input step="0.01" type="number" value={form.base_voltage} onChange={function (event) { onChange("base_voltage", Number(event.target.value)); }} />
                    </label>
                    <label>
                        <span>Base SOH</span>
                        <input step="0.1" type="number" value={form.base_soh} onChange={function (event) { onChange("base_soh", Number(event.target.value)); }} />
                    </label>
                    <label>
                        <span>Base Temperature</span>
                        <input step="0.1" type="number" value={form.base_temp} onChange={function (event) { onChange("base_temp", Number(event.target.value)); }} />
                    </label>
                    <label>
                        <span>Degradation</span>
                        <input step="0.01" type="number" value={form.degradation_rate} onChange={function (event) { onChange("degradation_rate", Number(event.target.value)); }} />
                    </label>
                    <label>
                        <span>Fault Probability</span>
                        <input step="0.1" type="number" value={form.fault_probability} onChange={function (event) { onChange("fault_probability", Number(event.target.value)); }} />
                    </label>
                </div>

                <label>
                    <span>Description</span>
                    <textarea rows="3" value={form.description} onChange={function (event) { onChange("description", event.target.value); }} />
                </label>

                <button className="toolbar-button primary" disabled={submitting} type="submit">
                    {submitting ? "Saving..." : "Save Battery"}
                </button>
            </form>
        </section>
    );
}

function UploadPanel({ notice, onUpload, uploading }) {
    const inputRef = useRef(null);

    return (
        <section className="panel form-panel">
            <div className="panel-header">
                <h2>Import Files</h2>
                <span>CSV / XLSX / JSON / TXT</span>
            </div>
            {notice ? <div className="notice inline">{notice}</div> : null}
            <div className="stack">
                <input multiple ref={inputRef} type="file" />
                <button
                    className="toolbar-button primary"
                    disabled={uploading}
                    onClick={async function handleUpload() {
                        if (!inputRef.current || !inputRef.current.files.length) {
                            return;
                        }

                        await onUpload(inputRef.current.files);
                        inputRef.current.value = "";
                    }}
                    type="button"
                >
                    {uploading ? "Uploading..." : "Upload and Create"}
                </button>
            </div>
        </section>
    );
}

function ConfirmDialog({ onCancel, onConfirm, open, title }) {
    if (!open) {
        return null;
    }

    return (
        <div className="confirm-backdrop" onClick={onCancel}>
            <div
                className="confirm-dialog"
                onClick={function stopPropagation(event) {
                    event.stopPropagation();
                }}
            >
                <h3>{title}</h3>
                <p>This action will permanently remove the custom battery.</p>
                <div className="confirm-actions">
                    <button className="toolbar-button subtle" onClick={onCancel} type="button">
                        Cancel
                    </button>
                    <button className="toolbar-button danger" onClick={onConfirm} type="button">
                        Delete
                    </button>
                </div>
            </div>
        </div>
    );
}

function MetricCard({ tone, label, value }) {
    return (
        <div className={"metric-card " + tone}>
            <div className="metric-label">{label}</div>
            <div className="metric-value">{value}</div>
        </div>
    );
}

function MonitoringCharts({ liveData }) {
    const historyCanvasRef = useRef(null);
    const forecastCanvasRef = useRef(null);
    const historyChartRef = useRef(null);
    const forecastChartRef = useRef(null);
    const deferredLiveData = useDeferredValue(liveData);

    useEffect(function cleanupCharts() {
        return function () {
            destroyChart(historyChartRef);
            destroyChart(forecastChartRef);
        };
    }, []);

    useEffect(function syncCharts() {
        if (!deferredLiveData) {
            return;
        }

        const history = deferredLiveData.long_term_forecast.history || [];
        const projection = deferredLiveData.long_term_forecast.projection || [];
        const historyGradient = historyCanvasRef.current.getContext("2d").createLinearGradient(0, 0, 0, 220);
        historyGradient.addColorStop(0, "rgba(59, 130, 246, 0.22)");
        historyGradient.addColorStop(1, "rgba(59, 130, 246, 0.02)");

        const forecastGradient = forecastCanvasRef.current.getContext("2d").createLinearGradient(0, 0, 0, 220);
        forecastGradient.addColorStop(0, "rgba(34, 197, 94, 0.18)");
        forecastGradient.addColorStop(1, "rgba(234, 179, 8, 0.05)");

        const sharedOptions = {
            responsive: true,
            maintainAspectRatio: false,
            plugins: { legend: { display: false }, tooltip: { enabled: true, displayColors: false } },
            scales: {
                x: {
                    display: true,
                    ticks: {
                        color: "#94a3b8",
                        maxTicksLimit: 5,
                        font: { size: 11 },
                    },
                    grid: {
                        color: "rgba(148, 163, 184, 0.18)",
                        drawBorder: false,
                    },
                    border: { display: false },
                },
                y: {
                    display: true,
                    ticks: {
                        color: "#94a3b8",
                        maxTicksLimit: 4,
                        font: { size: 11 },
                    },
                    grid: {
                        color: "rgba(148, 163, 184, 0.18)",
                        drawBorder: false,
                    },
                    border: { display: false },
                },
            },
            elements: { point: { radius: 0, hoverRadius: 4 } },
        };

        createOrUpdateChart(historyChartRef, historyCanvasRef, {
            type: "line",
            data: {
                labels: history.map(function (point) {
                    return new Date(point.timestamp * 1000).toLocaleDateString();
                }),
                datasets: [
                    {
                        data: history.map(function (point) {
                            return point.soh;
                        }),
                        borderColor: "#2f6db6",
                        backgroundColor: historyGradient,
                        borderWidth: 2.5,
                        fill: true,
                        tension: 0.4,
                    },
                ],
            },
            options: sharedOptions,
        });

        const lastHistory = history[history.length - 1];
        createOrUpdateChart(forecastChartRef, forecastCanvasRef, {
            type: "line",
            data: {
                labels: lastHistory
                    ? [new Date(lastHistory.timestamp * 1000).toLocaleDateString()].concat(
                        projection.map(function (point) {
                            return new Date(point.x * 1000).toLocaleDateString();
                        })
                    )
                    : [],
                datasets: [
                    {
                        data: lastHistory ? [lastHistory.soh].concat(new Array(projection.length).fill(null)) : [],
                        borderColor: "#22a05d",
                        backgroundColor: forecastGradient,
                        borderWidth: 2.2,
                        fill: true,
                        tension: 0.25,
                    },
                    {
                        data: lastHistory
                            ? [lastHistory.soh].concat(
                                projection.map(function (point) {
                                    return point.y;
                                })
                            )
                            : [],
                        borderColor: "#d89b3d",
                        borderDash: [5, 5],
                        borderWidth: 2,
                        fill: false,
                        tension: 0.25,
                    },
                ],
            },
            options: sharedOptions,
        });
    }, [deferredLiveData]);

    return (
        <div className="chart-grid">
            <section className="panel chart-panel">
                <div className="chart-meta">
                    <div>
                        <h2>SOH History</h2>
                        <strong>180 days</strong>
                    </div>
                </div>
                <canvas ref={historyCanvasRef}></canvas>
            </section>

            <section className="panel chart-panel">
                <div className="chart-meta">
                    <div>
                        <h2>24-Month Forecast</h2>
                        <strong>{liveData ? liveData.long_term_forecast.text : "--"}</strong>
                    </div>
                </div>
                <canvas ref={forecastCanvasRef}></canvas>
            </section>
        </div>
    );
}

function CellGrid({ cells }) {
    return (
        <section className="panel">
            <div className="panel-header">
                <h2>Cell Detail</h2>
                <span>{cells.length} cells</span>
            </div>
            <div className="cell-grid">
                {cells.map(function renderCell(cell) {
                    return (
                        <div className={"cell-card" + (cell.is_faulty ? " is-faulty" : "")} key={cell.id}>
                            <strong>Cell {cell.id}</strong>
                            <div className="cell-voltage">{formatMetric(cell.voltage, "V", 3)}</div>
                            <span>{formatMetric(cell.temperature, "°C", 1)}</span>
                        </div>
                    );
                })}
            </div>
        </section>
    );
}

function DashboardView({ onDelete, selected, liveData, onRefresh }) {
    if (!selected) {
        return (
            <section className="panel empty-panel">
                <h2>No battery selected</h2>
                <p>Select a preset or custom battery to load the dashboard.</p>
            </section>
        );
    }

    const summary = liveData && liveData.pack_summary ? liveData.pack_summary : null;
    const metrics = liveData && liveData.model_performance ? liveData.model_performance : { mae: "--", r2_score: "--" };
    const alertText = summary && summary.alert !== "None" ? summary.alert : "Healthy";

    return (
        <div className="dashboard-stack">
            <header className="topbar">
                <div>
                    <h1>IntelliBMS Battery Monitor</h1>
                    <p className="topbar-subtitle">{selected.name} / {selected.battery_type} / {alertText}</p>
                </div>
                <div className="topbar-actions">
                    <button className="toolbar-button primary" onClick={onRefresh} type="button">
                        Refresh Now
                    </button>
                    {selected.source === "custom" ? (
                        <button className="toolbar-button danger" onClick={function () { onDelete(selected.id); }} type="button">
                            Delete Battery
                        </button>
                    ) : null}
                </div>
            </header>

            <div className="metric-grid">
                <MetricCard tone="blue" label="Total Voltage" value={summary ? formatMetric(summary.total_voltage, "V", 2) : "--"} />
                <MetricCard tone="amber" label="Average Temperature" value={summary ? formatMetric(summary.avg_temperature, "°C", 1) : "--"} />
                <MetricCard tone="green" label="State of Health" value={summary ? formatMetric(summary.state_of_health, "%", 1) : "--"} />
                <MetricCard tone="violet" label="Model Accuracy" value={"MAE " + metrics.mae + " / R² " + metrics.r2_score} />
            </div>

            <MonitoringCharts liveData={liveData} />
            <CellGrid cells={liveData ? liveData.cells : []} />
        </div>
    );
}

function Workspace({
    activeSection,
    catalog,
    error,
    form,
    liveData,
    message,
    onChange,
    onDelete,
    onRefresh,
    onSectionChange,
    onSelect,
    onSubmit,
    onUpload,
    selected,
    submitting,
    uploading,
}) {
    const sectionNotice = error || message;

    return (
        <main className="workspace">
            {activeSection === "dashboard" ? <DashboardView liveData={liveData} onDelete={onDelete} onRefresh={onRefresh} selected={selected} /> : null}
            {activeSection === "preset" ? (
                <BatteryGrid
                    items={catalog.predefined}
                    onSelect={function (item) {
                        onSelect(item);
                        onSectionChange("dashboard");
                    }}
                    selected={selected}
                    title="Preset Batteries"
                />
            ) : null}
            {activeSection === "custom" ? (
                <BatteryGrid
                    items={catalog.custom}
                    onDelete={onDelete}
                    onSelect={function (item) {
                        onSelect(item);
                        onSectionChange("dashboard");
                    }}
                    selected={selected}
                    title="Custom Batteries"
                />
            ) : null}
            {activeSection === "add" ? <BatteryForm form={form} notice={sectionNotice} onChange={onChange} onSubmit={onSubmit} submitting={submitting} /> : null}
            {activeSection === "import" ? <UploadPanel notice={sectionNotice} onUpload={onUpload} uploading={uploading} /> : null}
        </main>
    );
}

function IntelliBMSApp() {
    const [activeSection, setActiveSection] = useState("dashboard");
    const [catalog, setCatalog] = useState({ predefined: [], custom: [] });
    const [selected, setSelected] = useState(null);
    const [liveData, setLiveData] = useState(null);
    const [submitting, setSubmitting] = useState(false);
    const [uploading, setUploading] = useState(false);
    const [message, setMessage] = useState("");
    const [error, setError] = useState("");
    const [form, setForm] = useState(DEFAULT_FORM);
    const [pendingDeleteId, setPendingDeleteId] = useState(null);

    function changeSection(section) {
        setMessage("");
        setError("");
        setActiveSection(section);
    }

    async function loadCatalog(preferred) {
        try {
            const payload = await window.IntelliBMSApi.getBatteryCatalog();
            startTransition(function () {
                setCatalog(payload);
                setSelected(function (previous) {
                    return selectPreferredBattery(payload, preferred || previous);
                });
            });
        } catch (requestError) {
            setError(requestError.message);
        }
    }

    async function loadLiveData(selection) {
        if (!selection) {
            return;
        }

        try {
            const payload = await window.IntelliBMSApi.getLiveData(selection);
            startTransition(function () {
                setLiveData(payload);
            });
        } catch (requestError) {
            setError(requestError.message);
        }
    }

    useEffect(function () {
        loadCatalog();
    }, []);

    useEffect(function () {
        if (!selected) {
            setLiveData(null);
            return;
        }

        loadLiveData(selected);
        const intervalId = window.setInterval(function () {
            loadLiveData(selected);
        }, 3000);

        return function () {
            window.clearInterval(intervalId);
        };
    }, [selectionKey(selected)]);

    function updateForm(field, value) {
        setForm(function (previous) {
            return { ...previous, [field]: value };
        });
    }

    async function handleSubmit(event) {
        event.preventDefault();
        setSubmitting(true);
        setError("");
        setMessage("");

        try {
            const createdBattery = await window.IntelliBMSApi.createBattery(form);
            setForm(DEFAULT_FORM);
            setMessage("");
            await loadCatalog({ id: createdBattery.id, source: "custom" });
            changeSection("dashboard");
        } catch (requestError) {
            setError(requestError.message);
        } finally {
            setSubmitting(false);
        }
    }

    async function handleUpload(files) {
        setUploading(true);
        setError("");
        setMessage("");

        try {
            const response = await window.IntelliBMSApi.uploadBatteryFiles(files);
            setMessage("");
            await loadCatalog({ id: response.battery_id, source: "custom" });
            changeSection("dashboard");
        } catch (requestError) {
            setError(requestError.message);
        } finally {
            setUploading(false);
        }
    }

    async function handleDelete(batteryId) {
        if (!batteryId) {
            return;
        }

        setError("");
        setMessage("");

        try {
            await window.IntelliBMSApi.deleteBattery(batteryId);
            setMessage("");
            setPendingDeleteId(null);
            await loadCatalog();
        } catch (requestError) {
            setError(requestError.message);
        }
    }

    return (
        <div className="app-shell">
            <Sidebar activeSection={activeSection} onSectionChange={changeSection} />
            <Workspace
                activeSection={activeSection}
                catalog={catalog}
                error={error}
                form={form}
                liveData={liveData}
                message={message}
                onChange={updateForm}
                onDelete={setPendingDeleteId}
                onRefresh={function () {
                    loadLiveData(selected);
                }}
                onSectionChange={changeSection}
                onSelect={setSelected}
                onSubmit={handleSubmit}
                onUpload={handleUpload}
                selected={selected}
                submitting={submitting}
                uploading={uploading}
            />
            <ConfirmDialog
                open={pendingDeleteId !== null}
                title="Delete this custom battery?"
                onCancel={function () {
                    setPendingDeleteId(null);
                }}
                onConfirm={function () {
                    handleDelete(pendingDeleteId);
                }}
            />
        </div>
    );
}

window.IntelliBMSApp = IntelliBMSApp;
