<?php

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

/**
 * Backfills the old `email_sends` + `sms_sends` rows into `contact_messages`,
 * then renames the legacy tables for safekeeping.  Drop in a follow-up release.
 *
 * solicitor_id on legacy rows is derived from the polymorphic `sendable` — where
 * possible — or falls back to config('contact.templates_backfill_solicitor_id').
 */
return new class extends Migration
{
    public function up(): void
    {
        $fallbackSolicitorId = config('contact.templates_backfill_solicitor_id');

        if (Schema::hasTable('email_sends')) {
            $this->backfillEmails($fallbackSolicitorId);
            Schema::rename('email_sends', 'email_sends_legacy');
        }

        if (Schema::hasTable('sms_sends')) {
            $this->backfillSms($fallbackSolicitorId);
            Schema::rename('sms_sends', 'sms_sends_legacy');
        }
    }

    public function down(): void
    {
        if (Schema::hasTable('email_sends_legacy')) {
            Schema::rename('email_sends_legacy', 'email_sends');
        }
        if (Schema::hasTable('sms_sends_legacy')) {
            Schema::rename('sms_sends_legacy', 'sms_sends');
        }
    }

    private function backfillEmails(?int $fallbackSolicitorId): void
    {
        DB::table('email_sends')->orderBy('id')->chunkById(500, function ($rows) use ($fallbackSolicitorId) {
            $insert = [];
            foreach ($rows as $r) {
                $solicitorId = $this->resolveSolicitorFromSendable($r->sendable_type, $r->sendable_id, $fallbackSolicitorId);
                if (!$solicitorId) {
                    continue;
                }

                $insert[] = [
                    'solicitor_id' => $solicitorId,
                    'channel' => 'email',
                    'direction' => 'outbound',
                    'provider' => $r->provider,
                    'status' => $this->normalizeStatus($r->status),
                    'origin_type' => 'manual',
                    'origin_detail' => json_encode(['legacy_source' => 'email_sends', 'legacy_id' => $r->id]),
                    'messageable_type' => $r->sendable_type,
                    'messageable_id' => $r->sendable_id,
                    'recipient_name' => $r->to_name,
                    'recipient_email' => $r->to_email,
                    'sender_display' => $r->from_name,
                    'sender_value' => $r->from_email,
                    'reply_to' => $r->reply_to,
                    'subject' => $r->subject,
                    'body_text' => $r->text_body,
                    'body_html' => $r->html_body,
                    'provider_message_id' => $r->provider_message_id,
                    'provider_payload' => $r->provider_response,
                    'failure_reason' => $r->error_message,
                    'sent_at' => $r->sent_at,
                    'created_at' => $r->created_at,
                    'updated_at' => $r->updated_at,
                ];
            }
            if ($insert) {
                DB::table('contact_messages')->insert($insert);
            }
        });
    }

    private function backfillSms(?int $fallbackSolicitorId): void
    {
        DB::table('sms_sends')->orderBy('id')->chunkById(500, function ($rows) use ($fallbackSolicitorId) {
            $insert = [];
            foreach ($rows as $r) {
                $solicitorId = $this->resolveSolicitorFromSendable($r->sendable_type, $r->sendable_id, $fallbackSolicitorId);
                if (!$solicitorId) {
                    continue;
                }

                $insert[] = [
                    'solicitor_id' => $solicitorId,
                    'channel' => 'sms',
                    'direction' => 'outbound',
                    'provider' => $r->provider,
                    'status' => $this->normalizeStatus($r->status),
                    'origin_type' => 'manual',
                    'origin_detail' => json_encode(['legacy_source' => 'sms_sends', 'legacy_id' => $r->id]),
                    'messageable_type' => $r->sendable_type,
                    'messageable_id' => $r->sendable_id,
                    'recipient_phone' => $r->to_number,
                    'sender_value' => $r->from_number,
                    'body_text' => $r->message,
                    'provider_message_id' => $r->provider_message_id,
                    'provider_payload' => $r->provider_response,
                    'failure_reason' => $r->error_message,
                    'sent_at' => $r->sent_at,
                    'created_at' => $r->created_at,
                    'updated_at' => $r->updated_at,
                ];
            }
            if ($insert) {
                DB::table('contact_messages')->insert($insert);
            }
        });
    }

    private function resolveSolicitorFromSendable(?string $type, ?int $id, ?int $fallback): ?int
    {
        if (!$type || !$id) {
            return $fallback;
        }

        try {
            $table = app($type)->getTable();
            if (!Schema::hasColumn($table, 'solicitor_id')) {
                return $fallback;
            }
            $row = DB::table($table)->where('id', $id)->value('solicitor_id');
            return $row ?: $fallback;
        } catch (\Throwable) {
            return $fallback;
        }
    }

    private function normalizeStatus(?string $legacy): string
    {
        return match (strtolower((string) $legacy)) {
            'pending', 'scheduled' => 'queued',
            'sending' => 'sending',
            'sent' => 'sent',
            'failed' => 'failed',
            default => 'queued',
        };
    }
};
