<?php

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

/**
 * The workspace layer that sits on top of laravel/ai's conversation store.
 *
 * The package owns the transcript (agent_conversations, agent_conversation_messages).
 * These tables add the three things a transcript cannot express:
 *
 *   - what a conversation produced, without the conversation owning it
 *   - which of those things the user is currently talking about
 *   - where each field value came from
 */
return new class extends Migration
{
    public function up(): void
    {
        // A conversation is a workspace, not a campaign. It may produce any
        // number of campaigns, landing pages, creatives or analyses, and it
        // owns none of them; deleting a chat must not delete a live campaign.
        Schema::create('conversation_artifacts', function (Blueprint $table): void {
            $table->id();
            $table->string('conversation_id', 36)->index();
            $table->morphs('artifactable');
            // The provider issues this, so it is not ours to size. OpenAI's is
            // 53 characters; a uuid-sized column truncated it and failed the insert.
            $table->string('created_by_message_id')->nullable();
            $table->timestamps();

            $table->unique(['conversation_id', 'artifactable_type', 'artifactable_id'], 'conversation_artifact_unique');
        });

        // "Make the budget $30" is ambiguous once a chat holds three campaigns,
        // so the workspace tracks what is currently in focus and the agent is
        // shown it every turn.
        Schema::create('conversation_states', function (Blueprint $table): void {
            $table->id();
            $table->string('conversation_id', 36)->unique();
            $table->nullableMorphs('focus');

            // Ownership is a team today. Storing it as a morph rather than a
            // team_id keeps the move to per-user or per-account a data change
            // rather than a schema rewrite.
            $table->nullableMorphs('owner');
            $table->timestamps();
        });

        // Provenance, kept off the artifact tables so creatives and landing
        // pages get it for free without every team altering their own schema.
        // A value the model guessed after a lookup failed must never reach a
        // platform without a human confirming it first.
        Schema::create('artifact_field_sources', function (Blueprint $table): void {
            $table->id();
            $table->morphs('artifactable');
            $table->string('field');
            $table->string('source', 32);   // user_stated|platform_returned|model_inferred|fallback
            $table->timestamps();

            $table->unique(['artifactable_type', 'artifactable_id', 'field'], 'artifact_field_unique');
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('artifact_field_sources');
        Schema::dropIfExists('conversation_states');
        Schema::dropIfExists('conversation_artifacts');
    }
};
