import { createEffect, createResource, createSignal, For, Show } from "solid-js";
import { MapView } from "../../components/map/MapView";
import { apiHost, ResultKeyVal } from "../../consts";
import { LoadingSpinner } from "../../components/spinner/LoadingSpinner";
import { faktiskaExport, faktiskaStations, FaktiskaStation } from "./faktiskaConfig";
import "./mapGraphics.css";

type LatestTemperature = { city: FaktiskaStation; observedAt: string; value: number | null };

const emptyValues = (): Record<FaktiskaStation, string> =>
    Object.fromEntries(faktiskaStations.map(city => [city, ""])) as Record<FaktiskaStation, string>;

export function Faktiska() {
    const [values, setValues] = createSignal(emptyValues());
    const [overrides, setOverrides] = createSignal<Set<FaktiskaStation>>(new Set());

    const fetchLatest = async (): Promise<LatestTemperature[]> => {
        const response = await fetch(`${apiHost}/api/query/latest-temperatures/${faktiskaStations.join(",")}`);
        if (!response.ok) throw new Error(`Latest observations failed (${response.status})`);
        return response.json();
    };
    const [latest, { refetch }] = createResource(fetchLatest);

    createEffect(() => {
        const observations = latest();
        if (!observations) return;
        const next = emptyValues();
        observations.forEach(observation => {
            next[observation.city] = observation.value == null ? "" : observation.value.toString();
        });
        setValues(next);
        setOverrides(new Set());
    });

    const observationsByCity = () => new Map((latest() ?? []).map(item => [item.city, item]));
    const newestTimestamp = () => {
        const timestamps = (latest() ?? []).map(item => Date.parse(item.observedAt)).filter(Number.isFinite);
        return timestamps.length ? new Date(Math.max(...timestamps)) : undefined;
    };
    const isStale = (city: FaktiskaStation) => {
        const newest = newestTimestamp();
        const observed = observationsByCity().get(city)?.observedAt;
        return Boolean(newest && observed && newest.getTime() - Date.parse(observed) > 90 * 60 * 1000);
    };
    const cityData = (): ResultKeyVal[] => faktiskaStations.flatMap(city => {
        const value = Number(values()[city].replace(",", "."));
        return values()[city].trim() && Number.isFinite(value) ? [[city, value] as ResultKeyVal] : [];
    });
    const updateValue = (city: FaktiskaStation, value: string) => {
        setValues(current => ({ ...current, [city]: value }));
        setOverrides(current => new Set(current).add(city));
    };
    const resetValue = (city: FaktiskaStation) => {
        const observation = observationsByCity().get(city);
        setValues(current => ({ ...current, [city]: observation?.value == null ? "" : observation.value.toString() }));
        setOverrides(current => {
            const next = new Set(current);
            next.delete(city);
            return next;
        });
    };

    return <div class="mapGraphicsPage pageWorkspace faktiskaWorkspace">
        <div class="pageHeading">
            <div><span class="eyebrow">Daily newsroom production</span><h1>Faktiskā</h1><p>Current temperatures with manually prepared weather symbols and wind.</p></div>
            <div class="productionSize">{faktiskaExport.width} × {faktiskaExport.height} PNG</div>
        </div>

        <section class="faktiskaDataBand">
            <div class="faktiskaStatus">
                <div><span class="stepLabel">1. Latest temperatures</span><strong>{newestTimestamp() ? newestTimestamp()!.toLocaleString("lv-LV") : "Waiting for observations"}</strong><small>Newest available reading in the configured station set</small></div>
                <button class="secondary" disabled={latest.loading} onClick={() => refetch()}>Refresh data</button>
            </div>
            <Show when={latest.loading}><LoadingSpinner text="Loading latest temperatures"/></Show>
            <Show when={latest.error}><div class="inlineNotice error"><strong>Could not load observations.</strong> Existing manual fields remain available.</div></Show>
            <div class="temperatureEditor">
                <For each={faktiskaStations}>{city => {
                    const observation = () => observationsByCity().get(city);
                    return <label class="temperatureField" classList={{manual: overrides().has(city), stale: isStale(city), missing: observation()?.value == null}}>
                        <span class="temperatureFieldHeading"><strong>{city}</strong><small>{overrides().has(city) ? "Manual" : isStale(city) ? "Older reading" : observation()?.observedAt ? new Date(observation()!.observedAt).toLocaleTimeString("lv-LV", {hour:"2-digit", minute:"2-digit"}) : "No data"}</small></span>
                        <span class="temperatureInput"><input type="text" inputmode="decimal" value={values()[city]} onInput={event => updateValue(city, event.currentTarget.value)} aria-label={`${city} temperature`}/><span>°C</span></span>
                        <button type="button" class="resetTemperature" disabled={!overrides().has(city)} onClick={() => resetValue(city)}>Reset</button>
                    </label>;
                }}</For>
            </div>
        </section>

        <section class="mapProduction faktiskaProduction">
            <h2>2. Add weather symbols and wind, then export</h2>
            <MapView type={faktiskaExport.mapType} data={cityData} mode="faktiska" productionTemplate/>
        </section>
    </div>;
}
