<script setup lang="ts">
import { ref, computed, onMounted, watch } from "vue"
import { useAppStore } from "@/stores/app"
import { deskewImage, waitForOpenCV } from "@/lib/deskew"
import type { RectDatum } from "@/types"
import { DEFAULT_SCALE_PX_PER_MM } from "@/types"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Progress } from "@/components/ui/progress"
import {
    Tooltip,
    TooltipContent,
    TooltipProvider,
    TooltipTrigger,
} from "@/components/ui/tooltip"
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import {
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableHeader,
    TableRow,
} from "@/components/ui/table"
import CorrectedImageViewer from "@/components/CorrectedImageViewer.vue"
import {
    loadSettings,
    saveSettings,
} from "@/lib/settings-cache"

const store = useAppStore()
const resultUrl = ref<string | null>(null)
const error = ref("")
const hasRun = ref(false)
const cvReady = ref(false)
const cvLoading = ref(false)
const showAlgoDetails = ref(false)
const includeScaleBar = ref(false)
const scaleInput = ref(String(store.scalePxPerMm))
const scaleValid = computed(() => {
    const n = Number(scaleInput.value)
    return Number.isFinite(n) && n > 0
})

watch(scaleInput, (v) => {
    const n = Number(v)
    if (Number.isFinite(n) && n > 0) {
        store.scalePxPerMm = n
    }
})

const MAX_AUTO_SCALE_DIM = 8192

function computeAutoScale(): number {
    const img = store.loadedImage
    const primary = store.datums.find(
        (d): d is RectDatum => d.type === "rectangle",
    )
    if (!img || !primary) return DEFAULT_SCALE_PX_PER_MM

    // Approximate source-pixel size of the datum
    const c = primary.corners
    const datumSrcW = Math.max(
        Math.hypot(c[1].x - c[0].x, c[1].y - c[0].y),
        Math.hypot(c[2].x - c[3].x, c[2].y - c[3].y),
    )
    const datumSrcH = Math.max(
        Math.hypot(c[3].x - c[0].x, c[3].y - c[0].y),
        Math.hypot(c[2].x - c[1].x, c[2].y - c[1].y),
    )

    // Scale that would make the datum the same pixel size as in source
    const sx =
        datumSrcW > 0 ? datumSrcW / primary.widthMm : 0
    const sy =
        datumSrcH > 0 ? datumSrcH / primary.heightMm : 0
    let autoScale = Math.max(sx, sy)

    // Clamp so the full output doesn't exceed MAX_AUTO_SCALE_DIM
    const estW = img.naturalWidth * autoScale / Math.max(datumSrcW / primary.widthMm, 0.001)
    const estH = img.naturalHeight * autoScale / Math.max(datumSrcH / primary.heightMm, 0.001)
    if (estW > MAX_AUTO_SCALE_DIM || estH > MAX_AUTO_SCALE_DIM) {
        autoScale *= MAX_AUTO_SCALE_DIM / Math.max(estW, estH)
    }

    // Round to a clean number
    return Math.max(1, Math.round(autoScale * 10) / 10)
}

onMounted(() => {
    const cached = loadSettings()
    if (cached) {
        includeScaleBar.value = cached.includeScaleBar
        // Only use cached scale if it was explicitly set before
        if (cached.scalePxPerMm !== DEFAULT_SCALE_PX_PER_MM) {
            scaleInput.value = String(cached.scalePxPerMm)
            return
        }
    }
    // Auto-compute a sensible default scale
    const auto = computeAutoScale()
    store.scalePxPerMm = auto
    scaleInput.value = String(auto)
})

watch(
    [() => store.scalePxPerMm, includeScaleBar],
    () => {
        saveSettings({
            scalePxPerMm: store.scalePxPerMm,
            includeScaleBar: includeScaleBar.value,
        })
    },
)

// Progress tracking
const progressStep = ref(0)
const progressTotal = ref(7)
const progressLabel = ref("")
const progressPercent = computed(() =>
    progressTotal.value > 0
        ? Math.round((progressStep.value / progressTotal.value) * 100)
        : 0,
)

// Estimated output size — accounts for full warped image, not just datum
const MAX_RGBA_MB = 512
const estimatedOutput = computed(() => {
    const primary = store.datums.find(
        (d): d is RectDatum => d.type === "rectangle",
    )
    const img = store.loadedImage
    if (!primary || !img || store.scalePxPerMm <= 0) return null

    // Datum dimensions in output pixels
    const datumOutW = primary.widthMm * store.scalePxPerMm
    const datumOutH = primary.heightMm * store.scalePxPerMm

    // Datum dimensions in source pixels (approximate from corner spread)
    const c = primary.corners
    const datumSrcW = Math.max(
        Math.hypot(c[1].x - c[0].x, c[1].y - c[0].y),
        Math.hypot(c[2].x - c[3].x, c[2].y - c[3].y),
    )
    const datumSrcH = Math.max(
        Math.hypot(c[3].x - c[0].x, c[3].y - c[0].y),
        Math.hypot(c[2].x - c[1].x, c[2].y - c[1].y),
    )

    // Scale factor from source to output (per-axis average)
    const sx =
        datumSrcW > 0 ? datumOutW / datumSrcW : store.scalePxPerMm
    const sy =
        datumSrcH > 0 ? datumOutH / datumSrcH : store.scalePxPerMm
    const avgScale = (sx + sy) / 2

    // Estimated full warped output = source image scaled
    const w = Math.round(img.naturalWidth * avgScale)
    const h = Math.round(img.naturalHeight * avgScale)
    const mb = (w * h * 4) / (1024 * 1024)
    return { w, h, mb, datumW: Math.round(datumOutW), datumH: Math.round(datumOutH) }
})

const tooLarge = computed(
    () => (estimatedOutput.value?.mb ?? 0) > MAX_RGBA_MB,
)

async function ensureOpenCV() {
    if (cvReady.value) return
    cvLoading.value = true
    store.processingStatus = "Loading OpenCV WASM..."
    await waitForOpenCV()
    cvReady.value = true
    cvLoading.value = false
}

async function runDeskew() {
    if (!store.loadedImage) return

    error.value = ""
    store.isProcessing = true
    hasRun.value = true

    try {
        await ensureOpenCV()

        store.processingStatus = "Running perspective correction..."
        progressStep.value = 0
        progressLabel.value = "Starting..."
        // Yield to let the browser repaint the spinner before heavy work
        await new Promise((r) => {
            requestAnimationFrame(r)
        })
        await new Promise((r) => {
            requestAnimationFrame(r)
        })

        const result = await deskewImage({
            image: store.loadedImage,
            datums: store.datums,
            exif: store.exifData,
            scalePxPerMm: store.scalePxPerMm,
            onProgress: (step, total, label) => {
                progressStep.value = step
                progressTotal.value = total
                progressLabel.value = label
                store.processingStatus = label
            },
        })

        store.setResult(result)

        if (resultUrl.value) URL.revokeObjectURL(resultUrl.value)
        resultUrl.value = URL.createObjectURL(result.correctedImageBlob)
    } catch (e) {
        error.value = e instanceof Error ? e.message : "Deskew failed"
    } finally {
        store.isProcessing = false
        store.processingStatus = ""
    }
}

function addScaleBar(image: HTMLImageElement): Promise<Blob> {
    return new Promise((resolve, reject) => {
        const iw = image.naturalWidth
        const ih = image.naturalHeight
        const scale = store.scalePxPerMm

        const unit = Math.max(iw / 100, 8)
        const barHeightPx = Math.round(unit * 5)
        const canvas = document.createElement("canvas")
        canvas.width = iw
        canvas.height = ih + barHeightPx

        const ctx = canvas.getContext("2d")
        if (!ctx) {
            reject(new Error("No 2D context"))
            return
        }

        ctx.drawImage(image, 0, 0)

        ctx.fillStyle = "#000"
        ctx.fillRect(0, ih, iw, barHeightPx)

        const imgWidthMm = iw / scale
        const niceSteps = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000]
        const targetMm = imgWidthMm * 0.2
        let barMm = niceSteps[0] ?? 10
        for (const s of niceSteps) {
            barMm = s
            if (s >= targetMm) break
        }
        const barWidthPx = barMm * scale

        const margin = Math.round(unit * 2)
        const barX = margin
        const barY = ih + barHeightPx / 2
        const barThick = Math.max(Math.round(unit * 0.6), 4)
        const tickH = Math.round(unit * 1.5)
        const tickW = Math.max(2, Math.round(unit * 0.15))

        ctx.fillStyle = "#fff"
        ctx.fillRect(barX, barY - barThick / 2, barWidthPx, barThick)
        ctx.fillRect(barX, barY - tickH / 2, tickW, tickH)
        ctx.fillRect(
            barX + barWidthPx - tickW,
            barY - tickH / 2,
            tickW,
            tickH,
        )

        const fontSize = Math.round(unit * 1.4)
        ctx.font = `bold ${String(fontSize)}px monospace`
        ctx.fillStyle = "#fff"
        ctx.textAlign = "center"
        ctx.textBaseline = "bottom"
        ctx.fillText(
            `${String(barMm)} mm`,
            barX + barWidthPx / 2,
            barY - tickH / 2 - Math.round(unit * 0.3),
        )

        const smallFont = Math.round(unit * 1)
        ctx.textAlign = "right"
        ctx.textBaseline = "middle"
        ctx.font = `${String(smallFont)}px monospace`
        ctx.fillStyle = "rgba(255,255,255,0.6)"
        ctx.fillText(`${String(scale)} px/mm`, iw - margin, barY)

        canvas.toBlob((b) => {
            if (b) resolve(b)
            else reject(new Error("toBlob failed"))
        }, "image/png")
    })
}

async function download() {
    if (!store.deskewResult) return

    let blob: Blob = store.deskewResult.correctedImageBlob

    console.log("[download] includeScaleBar =", includeScaleBar.value)
    if (includeScaleBar.value) {
        // Load the corrected image into an HTMLImageElement for drawing
        const imgUrl = URL.createObjectURL(
            store.deskewResult.correctedImageBlob,
        )
        try {
            const image = await new Promise<HTMLImageElement>(
                (resolve, reject) => {
                    const el = new Image()
                    el.onload = () => {
                        resolve(el)
                    }
                    el.onerror = () => {
                        reject(new Error("Failed to load image"))
                    }
                    el.src = imgUrl
                },
            )
            blob = await addScaleBar(image)
        } finally {
            URL.revokeObjectURL(imgUrl)
        }
    }

    const url = URL.createObjectURL(blob)
    const a = document.createElement("a")
    a.href = url
    const baseName =
        store.originalFile?.name.replace(/\.[^.]+$/, "") ?? "output"
    a.download = `${baseName}-skwik.png`
    a.click()
    URL.revokeObjectURL(url)
}

function hasRects(): boolean {
    return store.datums.some((d) => d.type === "rectangle")
}
</script>

<template>
    <div class="mx-auto max-w-4xl space-y-6">
        <div class="flex items-center justify-between">
            <div>
                <h2 class="text-xl font-semibold">Process &amp; Download</h2>
                <p class="text-sm text-muted-foreground">
                    Set the output scale, run perspective correction, and
                    download.
                </p>
            </div>
            <Button variant="outline" @click="store.goToStep(3)"
                >Back</Button
            >
        </div>

        <!-- Scale setting -->
        <Card>
            <CardHeader>
                <CardTitle class="text-base">Output Scale</CardTitle>
                <CardDescription>
                    Pixels per millimeter in the corrected output image.
                    Higher = larger output.
                </CardDescription>
            </CardHeader>
            <CardContent>
                <div class="flex items-center gap-3">
                    <Label>Scale</Label>
                    <Input
                        :model-value="scaleInput"
                        type="number"
                        min="1"
                        class="w-28 font-mono"
                        :class="
                            scaleValid
                                ? ''
                                : 'border-destructive ring-destructive/30 ring-2'
                        "
                        @update:model-value="
                            (v: string | number) =>
                                (scaleInput = String(v))
                        "
                    />
                    <span class="font-mono text-sm text-muted-foreground"
                        >px/mm</span
                    >
                </div>
                <!-- Estimated output size -->
                <div
                    v-if="estimatedOutput"
                    class="mt-3 space-y-1 text-sm"
                    :class="
                        tooLarge
                            ? 'text-destructive'
                            : 'text-muted-foreground'
                    "
                >
                    <p>
                        Est. output:
                        <span class="font-mono"
                            >~{{ estimatedOutput.w }}&times;{{
                                estimatedOutput.h
                            }}px</span
                        >
                        &ensp;&mdash;&ensp;
                        <span class="font-mono"
                            >~{{
                                estimatedOutput.mb.toFixed(0)
                            }} MB</span
                        >
                        RAM
                    </p>
                    <p v-if="!scaleValid" class="font-medium text-destructive">
                        Enter a valid scale &gt; 0.
                    </p>
                    <p v-else-if="tooLarge" class="font-medium">
                        Exceeds {{ MAX_RGBA_MB }} MB limit &mdash;
                        lower the scale or use a smaller source image.
                    </p>
                </div>
            </CardContent>
        </Card>

        <!-- Summary of datums -->
        <Card>
            <CardHeader>
                <CardTitle class="text-base">Datum Summary</CardTitle>
                <CardDescription>
                    {{ store.datums.length }} datum(s) will be used for
                    calibration.
                </CardDescription>
            </CardHeader>
            <CardContent>
                <div class="flex flex-wrap gap-2">
                    <Badge
                        v-for="datum in store.datums"
                        :key="datum.id"
                        variant="outline"
                        class="font-normal"
                    >
                        {{ datum.label }}
                        <span class="ml-1 font-mono text-xs">{{
                            datum.type === "rectangle"
                                ? `${datum.widthMm}\u00D7${datum.heightMm}mm`
                                : `${datum.lengthMm}mm`
                        }}</span>
                        <span class="ml-1 text-muted-foreground"
                            >conf {{ datum.confidence }}/5</span
                        >
                    </Badge>
                </div>
                <p
                    v-if="!hasRects()"
                    class="mt-3 text-sm text-destructive"
                >
                    At least one rectangle datum is required for perspective
                    correction.
                </p>
            </CardContent>
        </Card>

        <!-- Run button + progress -->
        <div class="flex flex-col items-center gap-3">
            <Button
                size="lg"
                :disabled="
                    store.isProcessing ||
                    !hasRects() ||
                    tooLarge ||
                    !scaleValid
                "
                @click="runDeskew"
            >
                <template v-if="store.isProcessing">
                    <svg
                        class="mr-2 h-4 w-4 animate-spin"
                        xmlns="http://www.w3.org/2000/svg"
                        fill="none"
                        viewBox="0 0 24 24"
                    >
                        <circle
                            class="opacity-25"
                            cx="12"
                            cy="12"
                            r="10"
                            stroke="currentColor"
                            stroke-width="4"
                        />
                        <path
                            class="opacity-75"
                            fill="currentColor"
                            d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
                        />
                    </svg>
                    {{ store.processingStatus || "Processing..." }}
                </template>
                <template v-else>
                    {{
                        hasRun
                            ? "Re-run Correction"
                            : "Run Perspective Correction"
                    }}
                </template>
            </Button>

            <!-- Progress bar -->
            <div
                v-if="store.isProcessing"
                class="w-full max-w-sm space-y-1.5"
            >
                <Progress :model-value="progressPercent" class="h-2" />
                <p
                    class="text-center font-mono text-xs text-muted-foreground"
                >
                    [{{ progressStep + 1 }}/{{ progressTotal }}]
                    {{ progressLabel }}
                </p>
            </div>
        </div>

        <p v-if="error" class="text-center text-sm text-destructive">
            {{ error }}
        </p>

        <!-- Result -->
        <template v-if="store.deskewResult && resultUrl">
            <!-- Diagnostics -->
            <Card>
                <CardHeader>
                    <CardTitle class="text-base">Diagnostics</CardTitle>
                    <CardDescription>
                        Primary reference:
                        <strong>{{
                            store.deskewResult.diagnostics.primaryDatum
                        }}</strong>
                        <span class="mx-1 text-muted-foreground/50"
                            >|</span
                        >
                        Output:
                        <span class="font-mono"
                            >{{
                                store.deskewResult.diagnostics.outputWidthPx
                            }}&times;{{
                                store.deskewResult.diagnostics.outputHeightPx
                            }}px</span
                        >
                        <span class="mx-1 text-muted-foreground/50"
                            >|</span
                        >
                        <span class="font-mono"
                            >{{
                                (
                                    store.deskewResult.diagnostics
                                        .outputWidthPx / store.scalePxPerMm
                                ).toFixed(1)
                            }}&times;{{
                                (
                                    store.deskewResult.diagnostics
                                        .outputHeightPx / store.scalePxPerMm
                                ).toFixed(1)
                            }}mm</span
                        >
                        <span class="mx-1 text-muted-foreground/50"
                            >|</span
                        >
                        <span class="font-mono"
                            >{{
                                (
                                    store.deskewResult.correctedImageBlob
                                        .size /
                                    1024 /
                                    1024
                                ).toFixed(1)
                            }} MB</span
                        >
                    </CardDescription>
                </CardHeader>
                <CardContent class="space-y-4">
                    <!-- Axis corrections -->
                    <div class="grid grid-cols-2 gap-4">
                        <div
                            class="rounded-md border border-border/50 p-3"
                        >
                            <p
                                class="text-xs font-medium uppercase tracking-wide text-muted-foreground"
                            >
                                X-axis correction
                            </p>
                            <p class="font-mono text-lg font-semibold">
                                {{
                                    (
                                        store.deskewResult.diagnostics
                                            .xCorrection.ratio * 100
                                    ).toFixed(2)
                                }}%
                            </p>
                            <p
                                class="font-mono text-xs text-muted-foreground"
                            >
                                w={{
                                    store.deskewResult.diagnostics.xCorrection.totalWeight.toFixed(
                                        1,
                                    )
                                }}
                            </p>
                        </div>
                        <div
                            class="rounded-md border border-border/50 p-3"
                        >
                            <p
                                class="text-xs font-medium uppercase tracking-wide text-muted-foreground"
                            >
                                Y-axis correction
                            </p>
                            <p class="font-mono text-lg font-semibold">
                                {{
                                    (
                                        store.deskewResult.diagnostics
                                            .yCorrection.ratio * 100
                                    ).toFixed(2)
                                }}%
                            </p>
                            <p
                                class="font-mono text-xs text-muted-foreground"
                            >
                                w={{
                                    store.deskewResult.diagnostics.yCorrection.totalWeight.toFixed(
                                        1,
                                    )
                                }}
                            </p>
                        </div>
                    </div>

                    <!-- Per-datum table -->
                    <Table
                        v-if="
                            store.deskewResult.diagnostics.perDatum.length >
                            0
                        "
                    >
                        <TableHeader>
                            <TableRow>
                                <TableHead>Datum</TableHead>
                                <TableHead>Type</TableHead>
                                <TableHead class="text-right"
                                    >Expected (mm)</TableHead
                                >
                                <TableHead class="text-right"
                                    >Measured (mm)</TableHead
                                >
                                <TableHead class="text-right"
                                    >Error</TableHead
                                >
                                <TableHead>Axis</TableHead>
                            </TableRow>
                        </TableHeader>
                        <TableBody>
                            <TableRow
                                v-for="report in store.deskewResult
                                    .diagnostics.perDatum"
                                :key="report.label"
                            >
                                <TableCell class="font-medium">{{
                                    report.label
                                }}</TableCell>
                                <TableCell>
                                    <Badge
                                        variant="outline"
                                        class="text-xs"
                                        >{{ report.type }}</Badge
                                    >
                                </TableCell>
                                <TableCell class="font-mono text-right">{{
                                    report.expectedMm.toFixed(1)
                                }}</TableCell>
                                <TableCell class="font-mono text-right">{{
                                    report.measuredMm.toFixed(1)
                                }}</TableCell>
                                <TableCell
                                    class="font-mono text-right"
                                    :class="
                                        report.errorPercent > 5
                                            ? 'text-destructive'
                                            : ''
                                    "
                                >
                                    {{ report.errorPercent.toFixed(1) }}%
                                </TableCell>
                                <TableCell>{{
                                    report.axisContribution
                                }}</TableCell>
                            </TableRow>
                        </TableBody>
                    </Table>
                </CardContent>
            </Card>

            <!-- Algorithm explanation -->
            <Card class="border-border/40">
                <CardContent class="pb-5 pt-5">
                    <button
                        class="flex w-full items-center gap-2 text-left text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
                        @click="
                            showAlgoDetails = !showAlgoDetails
                        "
                    >
                        <svg
                            xmlns="http://www.w3.org/2000/svg"
                            width="14"
                            height="14"
                            viewBox="0 0 24 24"
                            fill="none"
                            stroke="currentColor"
                            stroke-width="2"
                            stroke-linecap="round"
                            stroke-linejoin="round"
                            class="shrink-0 transition-transform duration-200"
                            :class="
                                showAlgoDetails
                                    ? 'rotate-90'
                                    : ''
                            "
                        >
                            <path d="m9 18 6-6-6-6" />
                        </svg>
                        How the algorithm works
                    </button>
                    <div
                        v-show="showAlgoDetails"
                        class="mt-4 pl-6"
                    >
                        <ol
                            class="list-decimal space-y-2 text-sm leading-relaxed text-muted-foreground marker:font-semibold marker:text-foreground/60"
                        >
                            <li>
                                The primary rectangle datum
                                defines a
                                <strong
                                    class="text-foreground/80"
                                    >homography</strong
                                >
                                &mdash; a 3&times;3 projective
                                transform mapping the
                                quadrilateral in the source
                                image to a true rectangle at
                                the specified real-world
                                dimensions.
                            </li>
                            <li>
                                Secondary datums (additional
                                rectangles or line segments)
                                provide
                                <strong
                                    class="text-foreground/80"
                                    >weighted correction
                                    factors</strong
                                >
                                for the X and Y axes. Each
                                secondary datum's contribution
                                is weighted by its confidence
                                score, refining the scale in
                                each axis independently.
                            </li>
                            <li>
                                The final correction is applied
                                as a single
                                <code
                                    class="rounded bg-muted px-1 py-0.5 font-mono text-xs text-foreground"
                                    >cv::warpPerspective</code
                                >
                                call via OpenCV WASM, producing
                                the output image at the
                                requested px/mm scale.
                            </li>
                        </ol>
                    </div>
                </CardContent>
            </Card>

            <!-- Corrected image with tools -->
            <Card>
                <CardHeader>
                    <CardTitle class="text-base"
                        >Corrected Image</CardTitle
                    >
                </CardHeader>
                <CardContent>
                    <CorrectedImageViewer
                        :image-url="resultUrl"
                        :scale-px-per-mm="store.scalePxPerMm"
                    />
                </CardContent>
            </Card>

            <!-- Download -->
            <div class="flex flex-col items-center gap-3 pb-8">
                <TooltipProvider>
                    <Tooltip>
                        <TooltipTrigger as-child>
                            <label
                                class="flex cursor-pointer items-center gap-2 select-none"
                            >
                                <input
                                    v-model="includeScaleBar"
                                    type="checkbox"
                                    class="h-4 w-4 accent-primary"
                                />
                                <span
                                    class="text-sm text-muted-foreground"
                                    >Include scale bar in export</span
                                >
                            </label>
                        </TooltipTrigger>
                        <TooltipContent side="top" class="max-w-xs">
                            Appends a black bar at the bottom of the
                            exported image with a measurement scale and
                            px/mm annotation.
                        </TooltipContent>
                    </Tooltip>
                </TooltipProvider>
                <div class="flex items-center gap-3">
                    <Button size="lg" @click="download">
                        <svg
                            xmlns="http://www.w3.org/2000/svg"
                            width="18"
                            height="18"
                            viewBox="0 0 24 24"
                            fill="none"
                            stroke="currentColor"
                            stroke-width="2"
                            stroke-linecap="round"
                            stroke-linejoin="round"
                            class="mr-2"
                        >
                            <path
                                d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"
                            />
                            <polyline points="7 10 12 15 17 10" />
                            <line
                                x1="12"
                                x2="12"
                                y1="15"
                                y2="3"
                            />
                        </svg>
                        Download PNG
                    </Button>
                    <Button
                        size="lg"
                        variant="outline"
                        @click="store.reset()"
                    >
                        Process New Image
                    </Button>
                </div>
                <p
                    class="font-mono text-sm text-muted-foreground"
                >
                    {{
                        store.deskewResult.diagnostics.outputWidthPx
                    }}&times;{{
                        store.deskewResult.diagnostics.outputHeightPx
                    }} px &mdash;
                    {{
                        (
                            store.deskewResult
                                .correctedImageBlob.size /
                            1024 /
                            1024
                        ).toFixed(1)
                    }} MB
                </p>
            </div>
        </template>
    </div>
</template>
