<?php

namespace Tests\Feature\Catalog;

use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Category;
use App\Domains\Catalog\Models\Inventory;
use App\Domains\Tenant\Models\Tenant;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;

class CatalogSchemaTest extends TestCase
{
    use RefreshDatabase;

    public function test_categories_are_enabled_by_default(): void
    {
        $this->assertTrue(Schema::hasColumn('categorias', 'is_enabled'));

        $category = Category::query()->create([
            'nombre' => 'Enabled category',
        ]);

        $this->assertTrue($category->is_enabled);
        $this->assertDatabaseHas('categorias', [
            'id' => $category->id,
            'is_enabled' => true,
        ]);
    }

    public function test_legacy_product_tables_are_replaced_by_catalog_tables(): void
    {
        $this->assertFalse(Schema::hasTable('productos'));
        $this->assertFalse(Schema::hasTable('productos_variantes'));
        $this->assertFalse(Schema::hasTable('products_attributes'));
        $this->assertFalse(Schema::hasTable('bundles'));
        $this->assertFalse(Schema::hasTable('bundle_items'));
        $this->assertTrue(Schema::hasTable('variantes'));
        $this->assertTrue(Schema::hasTable('item_attributes'));
        $this->assertTrue(Schema::hasColumn('item_attributes', 'sort_order'));
        $this->assertTrue(Schema::hasColumn('item_attributes', 'show_in_selector'));
        $this->assertTrue(Schema::hasColumn('item_attributes', 'ticket_label'));
        $this->assertTrue(Schema::hasTable('variant_values'));
    }

    public function test_catalog_items_contains_catalog_classification_and_optional_inventory(): void
    {
        $this->assertEqualsCanonicalizing([
            'id',
            'tenant_code',
            'category_id',
            'brand_id',
            'inventory_id',
            'type',
            'slug',
            'nombre',
            'descripcion',
            'precio',
            'inventory_policy',
            'max_units_per_user',
            'has_tickets',
            'validity_time_id',
        ], Schema::getColumnListing('catalog_items'));
    }

    public function test_bundle_components_directly_link_catalog_items(): void
    {
        $this->assertFalse(Schema::hasTable('bundle_compositions'));
        $this->assertEqualsCanonicalizing([
            'id',
            'bundle_catalog_item_id',
            'component_catalog_item_id',
            'component_variant_id',
            'quantity',
        ], Schema::getColumnListing('bundle_components'));
        $this->assertFalse(Schema::hasColumn('carrito_items', 'bundle_composition_id'));
    }

    public function test_inventories_have_no_polymorphic_columns(): void
    {
        $this->assertEqualsCanonicalizing([
            'id',
            'sold_units',
            'reserved_stock',
            'real_stock',
        ], Schema::getColumnListing('inventories'));
    }

    public function test_featured_catalog_tables_replace_legacy_group_items(): void
    {
        $this->assertFalse(Schema::hasTable('group_items'));
        $this->assertFalse(Schema::hasTable('featured_variants'));
        $this->assertEqualsCanonicalizing([
            'id',
            'tenant_code',
            'code',
            'source_type',
            'category_id',
            'product_layout',
            'group_layout',
            'group_name',
            'group_order',
        ], Schema::getColumnListing('featured_groups'));
        $this->assertEqualsCanonicalizing([
            'id',
            'featured_group_id',
            'catalog_item_id',
            'order',
        ], Schema::getColumnListing('featured_items'));
    }

    public function test_catalog_and_variant_attachments_share_the_catalog_pivot(): void
    {
        $this->assertFalse(Schema::hasTable('productos_attachments'));
        $this->assertFalse(Schema::hasTable('variantes_attachments'));
        $this->assertEqualsCanonicalizing([
            'id',
            'variant_id',
            'catalog_item_id',
            'attachment_id',
            'orden',
            'is_enabled',
        ], Schema::getColumnListing('catalog_items_attachments'));
    }

    public function test_catalog_item_can_have_no_variants_and_variant_requires_inventory(): void
    {
        $headerLogo = Attachment::query()->create([
            'path' => 'test/header.png',
            'filename' => 'header.png',
            'type' => AttachmentType::Image,
            'mime_type' => 'image/png',
        ]);
        $footerLogo = Attachment::query()->create([
            'path' => 'test/footer.png',
            'filename' => 'footer.png',
            'type' => AttachmentType::Image,
            'mime_type' => 'image/png',
        ]);
        $tenant = Tenant::query()->create([
            'codigo' => 'test-tenant',
            'nombre' => 'Test Tenant',
            'dominio' => 'test.local',
            'primary_color' => '#000000',
            'secondary_color' => '#000000',
            'danger_color' => '#000000',
            'success_color' => '#000000',
            'header_bg_color' => '#000000',
            'footer_bg_color' => '#000000',
            'header_logo_id' => $headerLogo->id,
            'footer_logo_id' => $footerLogo->id,
        ]);
        $inventory = Inventory::query()->create();
        $item = CatalogItem::query()->create([
            'tenant_code' => $tenant->codigo,
            'inventory_id' => $inventory->id,
            'slug' => 'item',
            'nombre' => 'Item',
            'precio' => 10,
        ]);

        $variantInventory = Inventory::query()->create();
        $variant = $item->variants()->create(['inventory_id' => $variantInventory->id]);
        $itemAttachment = Attachment::query()->create([
            'path' => 'test/item.png',
            'filename' => 'item.png',
            'type' => AttachmentType::Image,
            'mime_type' => 'image/png',
        ]);
        $variantAttachment = Attachment::query()->create([
            'path' => 'test/variant.png',
            'filename' => 'variant.png',
            'type' => AttachmentType::Image,
            'mime_type' => 'image/png',
        ]);

        $item->attachments()->attach($itemAttachment, ['orden' => 2]);
        $variant->attachments()->attach($variantAttachment, ['orden' => 3]);

        $this->assertTrue($variant->catalogItem->is($item));
        $this->assertTrue($variant->inventory->is($variantInventory));
        $this->assertTrue($item->attachments()->firstOrFail()->is($itemAttachment));
        $this->assertTrue($variant->attachments()->firstOrFail()->is($variantAttachment));
        $this->assertDatabaseHas('catalog_items_attachments', [
            'catalog_item_id' => $item->id,
            'variant_id' => null,
            'attachment_id' => $itemAttachment->id,
            'orden' => 2,
            'is_enabled' => true,
        ]);
        $this->assertDatabaseHas('catalog_items_attachments', [
            'catalog_item_id' => $item->id,
            'variant_id' => $variant->id,
            'attachment_id' => $variantAttachment->id,
            'orden' => 3,
            'is_enabled' => true,
        ]);
    }

    public function test_variants_can_override_catalog_item_use_dates(): void
    {
        $this->assertTrue(Schema::hasColumns('variantes', [
            'event_date_id',
        ]));
    }

    public function test_event_configuration_and_dates_belong_to_the_tenant(): void
    {
        $this->assertFalse(Schema::hasTable('events'));
        $this->assertTrue(Schema::hasColumns('tenants', [
            'event_title',
            'event_location',
            'event_date_text',
        ]));
        $this->assertEqualsCanonicalizing([
            'id',
            'tenant_code',
            'date',
            'time_start',
            'time_end',
        ], Schema::getColumnListing('event_dates'));
        $this->assertFalse(Schema::hasColumn('catalog_items', 'event_id'));
        $this->assertFalse(Schema::hasColumn('compras', 'event_id'));
    }
}
