<?php

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

/**
 * The two things a status page needs beyond "how is it right now".
 *
 * status_days — one row per component per day, written by a sampler. Without
 * it the ninety-day bar every real status page carries would have to be
 * invented, and an invented uptime figure on the one page whose entire job is
 * to be believed is worse than no figure. A day with no samples stays absent
 * from the table and is drawn as "not recorded" — never as green.
 *
 * incidents / incident_updates — the written record. An outage that is over is
 * not an outage that did not happen: the timeline stays, with the times it was
 * noticed, identified, and fixed, so a customer asking "what happened on the
 * 14th" gets an answer rather than a reassurance.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('status_days', function (Blueprint $table) {
            $table->id();
            $table->date('day');
            $table->string('component', 32);

            // Counts, not a percentage: the sampler adds to them all day and a
            // stored percentage would have to be recomputed on every write,
            // which is how a rounding error becomes a permanent record.
            $table->unsignedInteger('samples')->default(0);
            $table->unsignedInteger('operational')->default(0);
            $table->unsignedInteger('degraded')->default(0);
            $table->unsignedInteger('down')->default(0);
            $table->unsignedInteger('unknown')->default(0);

            $table->timestamps();

            $table->unique(['day', 'component']);
            $table->index('day');
        });

        Schema::create('incidents', function (Blueprint $table) {
            $table->id();
            $table->uuid()->unique();
            $table->string('title');

            // What a reader sees on the component, and what colours the day.
            $table->string('impact', 16)->default('degraded');   // degraded | down | maintenance

            // Which components it touched. JSON rather than a pivot table: the
            // component list is a fixed set defined in code, not rows anybody
            // can add, so a join table would be a table of foreign keys to
            // constants.
            $table->json('components');

            $table->timestamp('started_at');
            $table->timestamp('resolved_at')->nullable();

            // Drafts exist so an operator can write the first update carefully
            // while the outage is happening rather than publishing a sentence
            // they have to correct.
            $table->timestamp('published_at')->nullable();

            $table->string('created_by')->nullable();
            $table->timestamps();

            $table->index(['published_at', 'started_at']);
        });

        Schema::create('incident_updates', function (Blueprint $table) {
            $table->id();
            $table->foreignId('incident_id')->constrained()->cascadeOnDelete();
            $table->string('status', 16);   // investigating | identified | monitoring | resolved
            $table->text('body');
            $table->string('created_by')->nullable();
            $table->timestamps();

            $table->index(['incident_id', 'created_at']);
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('incident_updates');
        Schema::dropIfExists('incidents');
        Schema::dropIfExists('status_days');
    }
};
