<script lang="ts">
    import type { ResidualLoadPoint } from "$lib/strommix";

    /** Today's per-slot Last + Wetter-Erneuerbare. */
    let { points }: { points: ResidualLoadPoint[] } = $props();

    type Layout = {
        width: number;
        height: number;
        padX: number;
        padY: number;
        innerW: number;
        innerH: number;
    };
    const layout: Layout = $derived.by(() => {
        const width = 600;
        const height = 180;
        const padX = 36;
        const padY = 16;
        return {
            width,
            height,
            padX,
            padY,
            innerW: width - 2 * padX,
            innerH: height - 2 * padY,
        };
    });

    type Range = { minX: number; maxX: number; maxY: number };
    const range: Range = $derived.by(() => {
        if (points.length === 0) {
            return { minX: 0, maxX: 1, maxY: 1 };
        }
        const minX = points[0].unix;
        const maxX = points[points.length - 1].unix;
        const maxY = Math.max(
            ...points.map((p) => Math.max(p.loadMw, p.weatherRenewableMw)),
            1,
        );
        return { minX, maxX, maxY };
    });

    function xOf(unix: number): number {
        const span = range.maxX - range.minX || 1;
        return layout.padX + ((unix - range.minX) / span) * layout.innerW;
    }
    function yOf(mw: number): number {
        const span = range.maxY || 1;
        return layout.padY + (1 - mw / span) * layout.innerH;
    }

    const loadPath = $derived.by(() => {
        if (points.length === 0) return "";
        return points
            .map(
                (p, i) =>
                    `${i === 0 ? "M" : "L"} ${xOf(p.unix)} ${yOf(p.loadMw)}`,
            )
            .join(" ");
    });

    const renewPath = $derived.by(() => {
        if (points.length === 0) return "";
        return points
            .map(
                (p, i) =>
                    `${i === 0 ? "M" : "L"} ${xOf(p.unix)} ${yOf(p.weatherRenewableMw)}`,
            )
            .join(" ");
    });

    const gapPath = $derived.by(() => {
        if (points.length === 0) return "";
        const top = points
            .map(
                (p, i) =>
                    `${i === 0 ? "M" : "L"} ${xOf(p.unix)} ${yOf(p.loadMw)}`,
            )
            .join(" ");
        const bottom = points
            .slice()
            .reverse()
            .map((p) => `L ${xOf(p.unix)} ${yOf(p.weatherRenewableMw)}`)
            .join(" ");
        return `${top} ${bottom} Z`;
    });

    const ticks = $derived.by(() => {
        if (points.length === 0) return [];
        const result: { unix: number; label: string }[] = [];
        const start = new Date(range.minX * 1000);
        start.setMinutes(0, 0, 0);
        const end = new Date(range.maxX * 1000);
        for (let t = start.getTime(); t <= end.getTime(); t += 4 * 3_600_000) {
            const d = new Date(t);
            result.push({
                unix: Math.floor(t / 1000),
                label: d.getHours().toString().padStart(2, "0") + ":00",
            });
        }
        return result;
    });

    const yTicks = $derived.by(() => {
        const step = range.maxY > 60_000 ? 20_000 : 10_000;
        const out: { mw: number; label: string }[] = [];
        for (let mw = 0; mw <= range.maxY; mw += step) {
            out.push({ mw, label: `${mw / 1000} GW` });
        }
        return out;
    });
</script>

{#if points.length > 0}
    <figure class="m-0">
        <svg
            class="block h-auto w-full font-sans"
            viewBox="0 0 {layout.width} {layout.height}"
            role="img"
            aria-label="Residuallast heute: Last minus Wind und Solar im Tagesverlauf"
        >
            {#each yTicks as t (t.mw)}
                <line
                    stroke="var(--color-stein-200)"
                    stroke-width="1"
                    x1={layout.padX}
                    x2={layout.width - layout.padX}
                    y1={yOf(t.mw)}
                    y2={yOf(t.mw)}
                />
                <text
                    fill="var(--color-stein-500)"
                    font-size="10"
                    text-anchor="end"
                    x={layout.padX - 4}
                    y={yOf(t.mw) + 3}
                >
                    {t.label}
                </text>
            {/each}

            {#if gapPath}
                <path d={gapPath} fill="var(--color-fire-200)" fill-opacity="0.55" stroke="none" />
            {/if}
            {#if renewPath}
                <path
                    d={renewPath}
                    fill="none"
                    stroke="var(--color-wald-500)"
                    stroke-width="1.75"
                />
            {/if}
            {#if loadPath}
                <path
                    d={loadPath}
                    fill="none"
                    stroke="var(--color-stein-800)"
                    stroke-width="1.75"
                />
            {/if}

            {#each ticks as t (t.unix)}
                <line
                    stroke="var(--color-stein-200)"
                    stroke-width="1"
                    stroke-dasharray="2 3"
                    x1={xOf(t.unix)}
                    x2={xOf(t.unix)}
                    y1={layout.padY}
                    y2={layout.height - layout.padY}
                />
                <text
                    fill="var(--color-stein-500)"
                    font-size="10"
                    text-anchor="middle"
                    x={xOf(t.unix)}
                    y={layout.height - 2}
                >
                    {t.label}
                </text>
            {/each}
        </svg>
        <figcaption class="mt-2 flex flex-wrap gap-3 text-xs text-stein-600">
            <span class="inline-flex items-center gap-1.5">
                <span class="inline-block size-3 rounded-sm bg-stein-800"></span>
                Last
            </span>
            <span class="inline-flex items-center gap-1.5">
                <span class="inline-block size-3 rounded-sm bg-wald-500"></span>
                Wind + Solar
            </span>
            <span class="inline-flex items-center gap-1.5">
                <span class="inline-block size-3 rounded-sm bg-fire-200"></span>
                Residuallast (Lücke)
            </span>
        </figcaption>
    </figure>
{/if}
