<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

return new class extends Migration
{
    /** @var array<string, array{title: string, image: string, filename: string}> */
    private const BRANDING = [
        'fiesta_futbol_infantil' => [
            'title' => 'Fiesta Fútbol Infantil',
            'image' => 'images/tennants/fiesta_futbol_infantil/futbol_infantil_favicon.png',
            'filename' => 'futbol_infantil_favicon.png',
        ],
        'desfile_pura_tendencia' => [
            'title' => 'Desfile Pura Tendencia',
            'image' => 'images/tennants/desfile_pura_tendencia/pura_tendencia_favicon.png',
            'filename' => 'pura_tendencia_favicon.png',
        ],
    ];

    /** @var list<string> */
    private array $storedPaths = [];

    public function up(): void
    {
        try {
            DB::transaction(function (): void {
                foreach (self::BRANDING as $tenantCode => $branding) {
                    $tenant = DB::table('tenants')
                        ->where('codigo', $tenantCode)
                        ->first(['id', 'favicon_id']);

                    if ($tenant === null) {
                        continue;
                    }

                    $faviconId = $tenant->favicon_id;
                    $currentFilename = $faviconId === null
                        ? null
                        : DB::table('attachments')->where('id', $faviconId)->value('filename');

                    if ($currentFilename !== $branding['filename']) {
                        $faviconId = $this->storeFavicon(
                            $tenantCode,
                            $branding['image'],
                            $branding['filename'],
                        );
                    }

                    DB::table('tenants')
                        ->where('id', $tenant->id)
                        ->update([
                            'site_title' => $branding['title'],
                            'favicon_id' => $faviconId,
                            'updated_at' => now(),
                        ]);
                }
            });
        } catch (Throwable $throwable) {
            Storage::disk('s3')->delete($this->storedPaths);

            throw $throwable;
        }
    }

    public function down(): void
    {
        foreach (self::BRANDING as $tenantCode => $branding) {
            $tenant = DB::table('tenants')
                ->where('codigo', $tenantCode)
                ->first(['id', 'site_title', 'favicon_id']);

            if ($tenant === null) {
                continue;
            }

            $favicon = $tenant->favicon_id === null
                ? null
                : DB::table('attachments')->where('id', $tenant->favicon_id)->first();

            DB::table('tenants')
                ->where('id', $tenant->id)
                ->update([
                    'site_title' => $tenant->site_title === $branding['title'] ? null : $tenant->site_title,
                    'favicon_id' => $favicon?->filename === $branding['filename'] ? null : $tenant->favicon_id,
                    'updated_at' => now(),
                ]);

            if ($favicon?->filename === $branding['filename']) {
                Storage::disk('s3')->delete($favicon->path);
                DB::table('attachments')->where('id', $favicon->id)->delete();
            }
        }
    }

    private function storeFavicon(string $tenantCode, string $relativePath, string $filename): int
    {
        $sourcePath = public_path($relativePath);

        if (! is_file($sourcePath)) {
            throw new RuntimeException("Favicon not found at path: {$sourcePath}");
        }

        $contents = file_get_contents($sourcePath);

        if ($contents === false) {
            throw new RuntimeException("Could not read favicon at path: {$sourcePath}");
        }

        $key = (string) Str::uuid();
        $storedPath = "tenants/{$tenantCode}/{$key}.png";

        if (! Storage::disk('s3')->put($storedPath, $contents)) {
            throw new RuntimeException("Could not store favicon at path: {$storedPath}");
        }

        $this->storedPaths[] = $storedPath;

        return DB::table('attachments')->insertGetId([
            'key' => $key,
            'path' => $storedPath,
            'filename' => $filename,
            'type' => 'image',
            'mime_type' => 'image/png',
            'extension' => 'png',
            'size' => strlen($contents),
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }
};
