import { prisma } from "../src/core/prisma"

type StandardCashDrawerImpactMode = "NONE" | "INCREASE"

type ShopConfigCandidate = {
    id: string
    shopId: string
    method: string
    enabled: boolean
    revision: number
    cashDrawerImpactMode: string
}

function parseArgs(argv: string[]) {
    const args = new Set(argv)
    const shopIdArg = argv.find((arg) => arg.startsWith("--shop-id="))

    return {
        apply: args.has("--apply"),
        shopId: shopIdArg ? shopIdArg.slice("--shop-id=".length) : null,
    }
}

function resolveTargetMode(method: string): StandardCashDrawerImpactMode {
    return method === "CASH" ? "INCREASE" : "NONE"
}

function formatCandidate(candidate: ShopConfigCandidate) {
    return `${candidate.id} | shop=${candidate.shopId} | method=${candidate.method} | enabled=${candidate.enabled} | revision=${candidate.revision} | current=${candidate.cashDrawerImpactMode} | target=${resolveTargetMode(candidate.method)}`
}

async function loadCandidates(shopId: string | null): Promise<ShopConfigCandidate[]> {
    return prisma.shopPaymentMethodConfig.findMany({
        where: {
            ...(shopId ? { shopId } : {}),
            OR: [
                { method: "CASH", cashDrawerImpactMode: { not: "INCREASE" } },
                { method: { not: "CASH" }, cashDrawerImpactMode: { not: "NONE" } },
            ],
        },
        select: {
            id: true,
            shopId: true,
            method: true,
            enabled: true,
            revision: true,
            cashDrawerImpactMode: true,
        },
        orderBy: [
            { shopId: "asc" },
            { method: "asc" },
            { id: "asc" },
        ],
    })
}

async function main() {
    const { apply, shopId } = parseArgs(process.argv.slice(2))
    const candidates = await loadCandidates(shopId)

    console.log(`Mode: ${apply ? "APPLY" : "DRY_RUN"}`)
    if (shopId) console.log(`Shop filter: ${shopId}`)
    console.log(`Candidates: ${candidates.length}`)

    for (const candidate of candidates) {
        console.log(formatCandidate(candidate))
    }

    if (!apply || candidates.length === 0) {
        console.log(apply ? "No changes applied (nothing to update)." : "Dry-run complete. Re-run with --apply to persist changes.")
        return
    }

    await prisma.$transaction(
        candidates.map((candidate) => prisma.shopPaymentMethodConfig.update({
            where: { id: candidate.id },
            data: {
                cashDrawerImpactMode: resolveTargetMode(candidate.method),
                revision: { increment: 1 },
            },
        }))
    )

    console.log(`Updated: ${candidates.length}`)

    const remaining = await loadCandidates(shopId)
    console.log(`Remaining mismatches after apply: ${remaining.length}`)
}

main()
    .catch((error) => {
        console.error("Backfill failed:", error)
        process.exitCode = 1
    })
    .finally(async () => {
        await prisma.$disconnect()
    })
