<?php

use App\Models\Subscription;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

/**
 * How many months a customer gets for nothing by paying for a year.
 *
 * The yearly price was already there — one `plan_prices` row per term, each with
 * its own Stripe Price — but only as a total somebody typed. So nothing in the
 * system knew WHY 588 was the yearly figure for a package costing 49 a month,
 * and no page could say "two months free" without a second person working it out
 * by hand and writing it down somewhere it would then drift.
 *
 * The figure lives on the VERSION, beside the capabilities publication freezes,
 * because that is what it is: part of the terms a customer bought. The yearly
 * amount stays in `plan_prices` — Stripe charges an amount, not a discount — and
 * the console derives one from the other so the two cannot disagree.
 *
 * ## The backfill
 *
 * Read out of the prices that exist rather than defaulted to zero: an
 * installation already selling twelve-for-ten must not lose that on a deploy.
 * Only an exact division counts. A yearly price of 580 against a monthly of 49
 * is not "eleven and a bit months free", it is a figure somebody negotiated, and
 * 0 leaves it alone — the amount charged is untouched either way, only the
 * sentence beside it goes unsaid.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::table('plan_versions', function (Blueprint $table) {
            $table->unsignedTinyInteger('free_months')->default(0)->after('seats');
        });

        $monthly = DB::table('plan_prices')
            ->where('term', Subscription::TERM_MONTHLY)
            ->pluck('amount_cents', 'plan_version_id');

        foreach (DB::table('plan_prices')->where('term', Subscription::TERM_YEARLY)->get() as $yearly) {
            $perMonth = (int) ($monthly[$yearly->plan_version_id] ?? 0);

            if ($perMonth <= 0) {
                continue;
            }

            // Modulo, not a division compared against its own cast: PHP's `/`
            // returns an INT when two ints divide exactly, so `12 === 12.0` is
            // false and a check written that way rejects precisely the case it
            // was meant to accept. This one asks the only question there is —
            // does the monthly price go into the yearly one a whole number of
            // times.
            if ((int) $yearly->amount_cents % $perMonth !== 0) {
                continue;
            }

            $paidMonths = intdiv((int) $yearly->amount_cents, $perMonth);

            // Inside the year. Anything else was priced by hand and is left to
            // speak for itself.
            if ($paidMonths < 1 || $paidMonths > 12) {
                continue;
            }

            DB::table('plan_versions')
                ->where('id', $yearly->plan_version_id)
                ->update(['free_months' => 12 - $paidMonths]);
        }
    }

    public function down(): void
    {
        Schema::table('plan_versions', function (Blueprint $table) {
            $table->dropColumn('free_months');
        });
    }
};
