<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Livewire\TrustSites\WebsiteReviews;
use App\Livewire\TrustSites\WebsitesIndex;
use App\Models\ReviewedWebsite;
use App\Models\ReviewedWebsiteReview;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;

final class TrustDirectoryTest extends TestCase
{
    use RefreshDatabase;

    public function test_public_directory_lists_published_websites_only(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Visible Trust Site',
            'slug' => 'visible-trust-site',
            'domain' => 'visible.example',
        ]);
        ReviewedWebsite::factory()->create([
            'name' => 'Draft Hidden',
            'slug' => 'draft-hidden',
            'domain' => 'hidden.example',
            'status' => ReviewedWebsite::STATUS_DRAFT,
        ]);

        $this->get('/websites')
            ->assertStatus(200)
            ->assertDontSee('Visible Trust Site', false)
            ->assertDontSee('Draft Hidden', false);

        Livewire::test(WebsitesIndex::class)
            ->set('search', 'visible.example')
            ->call('checkLegitimacy')
            ->assertSee('Visible Trust Site', false)
            ->assertDontSee('Draft Hidden', false);
    }

    public function test_public_directory_lists_featured_websites_first(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Alpha Regular',
            'slug' => 'alpha-regular',
            'domain' => 'alpha.example',
            'is_featured' => false,
            'featured_order' => 0,
        ]);
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Zebra Featured',
            'slug' => 'zebra-featured',
            'domain' => 'zebra.example',
            'is_featured' => true,
            'featured_order' => 1,
        ]);

        $html = Livewire::test(WebsitesIndex::class)
            ->set('search', 'example')
            ->call('checkLegitimacy')
            ->html();

        $zebraPos = strpos($html, 'Zebra Featured');
        $alphaPos = strpos($html, 'Alpha Regular');
        $this->assertNotFalse($zebraPos);
        $this->assertNotFalse($alphaPos);
        $this->assertLessThan($alphaPos, $zebraPos);
    }

    public function test_public_show_returns_404_for_draft(): void
    {
        ReviewedWebsite::factory()->create([
            'slug' => 'not-published',
            'status' => ReviewedWebsite::STATUS_DRAFT,
        ]);

        $this->get('/websites/not-published')->assertNotFound();
    }

    public function test_public_show_outputs_custom_meta_description_for_seo(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Acme Shop',
            'slug' => 'acme-shop-seo',
            'domain' => 'acme.example',
            'meta_description' => 'Unique trust-check snippet for Acme Shop research.',
        ]);

        $this->get(route('websites.show', 'acme-shop-seo'))
            ->assertOk()
            ->assertSee('Unique trust-check snippet for Acme Shop research.', false);
    }

    public function test_public_show_displays_legitimacy_meter_when_score_present(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'slug' => 'meter-demo',
            'manual_trust_score' => 72,
            'trust_score' => null,
        ]);

        $this->get(route('websites.show', 'meter-demo'))
            ->assertOk()
            ->assertSee('Authenticity meter', false)
            ->assertSee('30% scam', false)
            ->assertSee('40% legit', false);
    }

    public function test_public_show_displays_authenticity_from_editorial_when_no_numeric_scores(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'slug' => 'editorial-score-only',
            'manual_trust_score' => null,
            'trust_score' => null,
            'editorial_verdict' => ReviewedWebsite::VERDICT_MIXED,
        ]);

        $this->get(route('websites.show', 'editorial-score-only'))
            ->assertOk()
            ->assertSee('Authenticity rating', false)
            ->assertSee('45', false)
            ->assertSee('Derived from the editorial verdict', false)
            ->assertSee('Authenticity meter', false);
    }

    public function test_public_index_search_finds_by_slug(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Slug Match Inc',
            'slug' => 'slug-match-inc',
            'domain' => 'slugmatch.example',
        ]);

        Livewire::test(WebsitesIndex::class)
            ->set('search', 'slug-match-inc')
            ->call('checkLegitimacy')
            ->assertSee('Slug Match Inc', false);
    }

    public function test_public_index_search_finds_by_url_with_scheme_and_www(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Host Search Ltd',
            'slug' => 'host-search',
            'domain' => 'hostsearch.example',
            'website_url' => 'https://hostsearch.example/',
        ]);

        Livewire::test(WebsitesIndex::class)
            ->set('search', 'https://www.hostsearch.example')
            ->call('checkLegitimacy')
            ->assertSee('Host Search Ltd', false);
    }

    public function test_public_index_shows_compact_legitimacy_meter(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Meter Card Co',
            'slug' => 'meter-card',
            'manual_trust_score' => 85,
        ]);

        Livewire::test(WebsitesIndex::class)
            ->set('search', 'meter-card')
            ->call('checkLegitimacy')
            ->assertSee('Meter Card Co', false)
            ->assertSee('Authenticity', false);
    }

    public function test_public_index_shows_no_matches_until_check_legitimacy_clicked(): void
    {
        ReviewedWebsite::factory()->published()->create([
            'name' => 'Later Visible Co',
            'slug' => 'later-visible',
            'domain' => 'latervisible.example',
        ]);

        Livewire::test(WebsitesIndex::class)
            ->set('search', 'latervisible')
            ->assertDontSee('Later Visible Co', false);

        Livewire::test(WebsitesIndex::class)
            ->set('search', 'latervisible')
            ->call('checkLegitimacy')
            ->assertSee('Later Visible Co', false);
    }

    public function test_public_index_empty_check_shows_validation_message(): void
    {
        Livewire::test(WebsitesIndex::class)
            ->set('search', '   ')
            ->call('checkLegitimacy')
            ->assertSee('Please enter a website name or URL', false);
    }

    public function test_community_reviews_are_paginated_ten_per_page(): void
    {
        $site = ReviewedWebsite::factory()->published()->create();

        ReviewedWebsiteReview::factory()
            ->count(12)
            ->for($site)
            ->approved()
            ->create();

        Livewire::test(WebsiteReviews::class, ['websiteId' => $site->id])
            ->assertViewHas('reviews', function ($reviews): bool {
                return $reviews->count() === 10
                    && $reviews->total() === 12
                    && $reviews->hasPages();
            });
    }

    public function test_guest_can_submit_pending_website_review(): void
    {
        $site = ReviewedWebsite::factory()->published()->create([
            'slug' => 'submit-target',
            'domain' => 'submit.example',
        ]);

        Livewire::test(WebsiteReviews::class, ['websiteId' => $site->id])
            ->set('guestName', 'Jamie Guest')
            ->set('rating', 4)
            ->set('userVerdict', ReviewedWebsiteReview::VERDICT_LEGIT)
            ->set('body', 'Seemed fine to me.')
            ->call('submit')
            ->assertHasNoErrors();

        $this->assertDatabaseHas('reviewed_website_reviews', [
            'reviewed_website_id' => $site->id,
            'guest_name' => 'Jamie Guest',
            'status' => ReviewedWebsiteReview::STATUS_PENDING,
            'rating' => 4,
        ]);
    }

    public function test_approving_review_updates_trust_score(): void
    {
        $site = ReviewedWebsite::factory()->published()->create();
        $review = ReviewedWebsiteReview::factory()->for($site)->create([
            'rating' => 5,
            'user_verdict' => ReviewedWebsiteReview::VERDICT_LEGIT,
            'status' => ReviewedWebsiteReview::STATUS_PENDING,
        ]);

        $review->update(['status' => ReviewedWebsiteReview::STATUS_APPROVED]);

        $site->refresh();
        $this->assertSame(100, $site->trust_score);
        $this->assertSame(1, $site->approved_reviews_count);
    }
}
