<?php

declare(strict_types=1);

use App\Models\Artwork;
use App\Models\Tag;
use App\Services\TagNormalizer;
use App\Services\TagService;
use Illuminate\Support\Facades\DB;

it('normalizes tags consistently', function () {
    $n = app(TagNormalizer::class);

    expect($n->normalize('  Cyber Punk!! '))->toBe('cyber-punk');
    expect($n->normalize("🚀 Rocket  "))->toBe('rocket');
    expect($n->normalize(''))->toBe('');
});

it('prevents duplicate tags and duplicate pivots for user tags', function () {
    $service = app(TagService::class);
    $artwork = Artwork::factory()->create();

    $service->attachUserTags($artwork, ['CyberPunk', ' cyberpunk ', 'CYBERPUNK']);

    expect(Tag::query()->count())->toBe(1);
    expect($artwork->tags()->count())->toBe(1);
    expect(Tag::first()->usage_count)->toBe(1);
});

it('attaches AI tags with source and confidence without blocking existing user tags', function () {
    $service = app(TagService::class);
    $artwork = Artwork::factory()->create();

    $service->attachUserTags($artwork, ['city']);
    $service->attachAiTags($artwork, [
        ['tag' => 'city', 'confidence' => 0.2],
        ['tag' => 'cyberpunk', 'confidence' => 0.42],
    ]);

    $artwork->load('tags');
    $city = $artwork->tags->firstWhere('slug', 'city');
    $cyber = $artwork->tags->firstWhere('slug', 'cyberpunk');

    expect($city)->not->toBeNull();
    expect($city->pivot->source)->toBe('user');
    expect($city->pivot->confidence)->toBeNull();

    expect($cyber)->not->toBeNull();
    expect($cyber->pivot->source)->toBe('ai');
    expect($cyber->pivot->confidence)->toBeFloat();
});

it('syncs user tags and maintains usage counts', function () {
    $service = app(TagService::class);
    $artwork = Artwork::factory()->create();

    $service->attachUserTags($artwork, ['one', 'two']);
    expect(Tag::query()->whereIn('slug', ['one', 'two'])->pluck('usage_count', 'slug')->all())
        ->toMatchArray(['one' => 1, 'two' => 1]);

    $service->syncTags($artwork, ['two', 'three']);
    $artwork->refresh();

    expect($artwork->tags()->pluck('slug')->all())->toContain('two', 'three');

    $counts = Tag::query()->whereIn('slug', ['one', 'two', 'three'])->pluck('usage_count', 'slug')->all();
    expect($counts['one'])->toBe(0);
    expect($counts['two'])->toBe(1);
    expect($counts['three'])->toBe(1);
});

it('enforces pivot integrity (single row per artwork-tag) and user precedence', function () {
    $service = app(TagService::class);
    $artwork = Artwork::factory()->create();

    $service->attachAiTags($artwork, [['tag' => 'future', 'confidence' => 0.31]]);
    $service->attachUserTags($artwork, ['future']);

    $artwork->load('tags');
    $future = $artwork->tags->firstWhere('slug', 'future');

    expect($future)->not->toBeNull();
    expect($future->pivot->source)->toBe('user');
    expect($future->pivot->confidence)->toBeNull();
    expect(DB::table('artwork_tag')->where('artwork_id', $artwork->id)->where('tag_id', $future->id)->count())->toBe(1);
});

it('cleans up pivots and decrements usage counts when artwork is force deleted', function () {
    $service = app(TagService::class);
    $artwork = Artwork::factory()->create();

    $service->attachUserTags($artwork, ['a', 'b']);
    $tagIds = Tag::query()->pluck('id')->all();

    expect(DB::table('artwork_tag')->where('artwork_id', $artwork->id)->count())->toBe(2);
    $artwork->forceDelete();

    expect(DB::table('artwork_tag')->whereIn('tag_id', $tagIds)->count())->toBe(0);
    expect(Tag::query()->whereIn('id', $tagIds)->sum('usage_count'))->toBe(0);
});
