<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

/**
 * What it takes to charge a reverse-charge business the figure it actually owes.
 *
 * The catalogue was mirrored into Stripe at ONE amount per priced row — the
 * domestic gross — because a Stripe Price carries a single figure and was taken
 * to be unable to ask who is buying. For a domestic customer that is exactly
 * right, business or private: the VAT is on the invoice and an Austrian business
 * reclaims it as input tax, so the gross is a pass-through and the price on the
 * website is the price charged.
 *
 * It breaks for the one case where no VAT is charged at all. A business in
 * another member state with a VERIFIED VAT id gets reverse charge — rate zero,
 * no VAT line, the note on the document — and was still charged 214,80 € for a
 * 179,00 € package, with the document then stating the whole 214,80 € as net at
 * 0 %. There is no VAT line on it for them to reclaim, so it was a flat 20 %
 * surcharge on precisely the customers who read their invoices, and they
 * self-accounted their own VAT on a base a fifth too big.
 *
 * So a Price CAN ask who is buying: there are two of them per sellable thing,
 * and the checkout picks. The domestic gross and the bare net, both live, both
 * pointing at the same Product — and `reverse_charge` below is what says which
 * is which, on both sides of the mirror.
 *
 * `plan_prices.stripe_price_id` keeps its meaning untouched: the Price an
 * ordinary domestic customer is sold on. Nothing but a reverse-charge business
 * is ever sold on the net one, so it gets no column of its own on the catalogue
 * row and is read out of the register here instead.
 *
 * What a running contract is billed on stays readable, which is the whole reason
 * these registers are tables: `subscriptions.stripe_price_id` names the Price,
 * and joining it here says whether that Price is the gross or the net one — so a
 * customer whose registration is verified next week, or whose registration
 * lapses, can be seen to be on the wrong one and moved.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::table('stripe_plan_prices', function (Blueprint $table) {
            // Which of the two Prices for this row it is. False is the ordinary
            // sale and therefore the default: every Price that already exists
            // was minted for a domestic customer, whatever it happens to charge.
            $table->boolean('reverse_charge')->default(false)->after('plan_price_id');

            // The old key was (row, figure), which cannot hold both Prices at a
            // rate of nought — where the gross and the net are the same number —
            // and, worse, could not say which of two rows at one figure the
            // checkout should pick. The treatment belongs in the identity.
            $table->dropUnique('stripe_plan_prices_unique');
            $table->unique(['plan_price_id', 'reverse_charge', 'charged_cents'], 'stripe_plan_prices_unique');
        });

        Schema::table('stripe_addon_prices', function (Blueprint $table) {
            $table->boolean('reverse_charge')->default(false)->after('addon_key');

            $table->dropUnique('stripe_addon_prices_unique');
            $table->unique(
                ['addon_key', 'reverse_charge', 'amount_cents', 'currency', 'interval'],
                'stripe_addon_prices_unique',
            );

            // Read when a Price is superseded by a rate change, which happens
            // within ONE treatment: the gross Price for today's figure moves and
            // the net one beside it does not, so the treatment has to be part of
            // the index the sweep reads or it would archive the other half.
            $table->dropIndex('stripe_addon_prices_net');
            $table->index(
                ['addon_key', 'reverse_charge', 'net_cents', 'currency', 'interval'],
                'stripe_addon_prices_net',
            );
        });
    }

    public function down(): void
    {
        Schema::table('stripe_addon_prices', function (Blueprint $table) {
            $table->dropIndex('stripe_addon_prices_net');
            $table->dropUnique('stripe_addon_prices_unique');
            $table->dropColumn('reverse_charge');
            $table->unique(['addon_key', 'amount_cents', 'currency', 'interval'], 'stripe_addon_prices_unique');
            $table->index(['addon_key', 'net_cents', 'currency', 'interval'], 'stripe_addon_prices_net');
        });

        Schema::table('stripe_plan_prices', function (Blueprint $table) {
            $table->dropUnique('stripe_plan_prices_unique');
            $table->dropColumn('reverse_charge');
            $table->unique(['plan_price_id', 'charged_cents'], 'stripe_plan_prices_unique');
        });
    }
};
