<?php

use App\Livewire\Studio\Setting\Application;
use App\Settings\ContactSettings;
use App\Settings\GeneralSettings;
use App\Settings\SeoSettings;
use App\Settings\SocialSettings;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

beforeEach(function () {
    $this->setupUser();

    $role = Role::firstOrCreate(['name' => 'Owner']);
    Permission::firstOrCreate(['name' => 'view application settings']);
    Permission::firstOrCreate(['name' => 'update general settings']);
    Permission::firstOrCreate(['name' => 'update contact settings']);
    Permission::firstOrCreate(['name' => 'update social settings']);
    Permission::firstOrCreate(['name' => 'update seo settings']);
    $role->givePermissionTo([
        'view application settings',
        'update general settings',
        'update contact settings',
        'update social settings',
        'update seo settings',
    ]);
    $this->user->assignRole($role);
});

it('renders the application settings page correctly', function () {
    $this->actingAs($this->user)
        ->get(route('studio.setting.application'))
        ->assertOk()
        ->assertSeeLivewire(Application::class);
});

it('loads general settings on mount', function () {
    $generalSettings = app(GeneralSettings::class);

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->assertSet('generalForm.site_name', $generalSettings->site_name)
        ->assertSet('generalForm.site_tagline', $generalSettings->site_tagline)
        ->assertSet('generalForm.site_description', $generalSettings->site_description)
        ->assertSet('generalForm.maintenance_mode', $generalSettings->maintenance_mode);
});

it('loads contact settings on mount', function () {
    $contactSettings = app(ContactSettings::class);

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->assertSet('contactForm.phone_number', $contactSettings->phone_number)
        ->assertSet('contactForm.email', $contactSettings->email)
        ->assertSet('contactForm.address', $contactSettings->address);
});

it('loads social settings on mount', function () {
    $socialSettings = app(SocialSettings::class);

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->assertSet('socialForm.facebook', $socialSettings->facebook)
        ->assertSet('socialForm.instagram', $socialSettings->instagram)
        ->assertSet('socialForm.youtube', $socialSettings->youtube);
});

it('loads seo settings on mount', function () {
    $seoSettings = app(SeoSettings::class);

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->assertSet('seoForm.meta_description', $seoSettings->meta_description)
        ->assertSet('seoForm.meta_keywords', $seoSettings->meta_keywords)
        ->assertSet('seoForm.meta_author', $seoSettings->meta_author);
});

// General Settings Tests
it('shows validation errors when updating general settings with empty fields', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('generalForm.site_name', '')
        ->set('generalForm.site_tagline', '')
        ->set('generalForm.site_description', '')
        ->call('updateGeneral')
        ->assertHasErrors([
            'generalForm.site_name' => 'required',
            'generalForm.site_tagline' => 'required',
            'generalForm.site_description' => 'required',
        ]);
});

it('shows validation error when site name is too long', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('generalForm.site_name', str_repeat('a', 101))
        ->call('updateGeneral')
        ->assertHasErrors([
            'generalForm.site_name' => 'max',
        ]);
});

it('shows validation error when site description is too short', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('generalForm.site_description', 'Short')
        ->call('updateGeneral')
        ->assertHasErrors([
            'generalForm.site_description' => 'min',
        ]);
});

it('can update general settings successfully', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('generalForm.site_name', 'New Site Name')
        ->set('generalForm.site_tagline', 'New Tagline')
        ->set('generalForm.site_description', 'This is a new site description with enough characters')
        ->set('generalForm.maintenance_mode', false)
        ->call('updateGeneral')
        ->assertHasNoErrors();

    $generalSettings = app(GeneralSettings::class);
    expect($generalSettings->site_name)->toBe('New Site Name');
    expect($generalSettings->site_tagline)->toBe('New Tagline');
    expect($generalSettings->site_description)->toBe('This is a new site description with enough characters');
    expect($generalSettings->maintenance_mode)->toBe(false);
});

it('cannot update general settings without permission', function () {
    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('generalForm.site_name', 'New Name')
        ->call('updateGeneral')
        ->assertForbidden();
});

// Contact Settings Tests
it('shows validation errors when updating contact settings with empty required fields', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('contactForm.phone_number', '')
        ->set('contactForm.address', '')
        ->call('updateContact')
        ->assertHasErrors([
            'contactForm.phone_number' => 'required',
            'contactForm.address' => 'required',
        ]);
});

it('shows validation error when phone number is too short', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('contactForm.phone_number', '123')
        ->call('updateContact')
        ->assertHasErrors([
            'contactForm.phone_number',
        ]);
});

it('shows validation error when email is invalid', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('contactForm.email', 'invalid-email')
        ->call('updateContact')
        ->assertHasErrors([
            'contactForm.email' => 'email',
        ]);
});

it('shows validation error when address is too short', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('contactForm.address', 'Short')
        ->call('updateContact')
        ->assertHasErrors([
            'contactForm.address' => 'min',
        ]);
});

it('can update contact settings successfully', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('contactForm.phone_number', '0812 3456 7890')
        ->set('contactForm.email', 'contact@example.com')
        ->set('contactForm.address', 'Jl. Example No. 123, Jakarta')
        ->set('contactForm.map_embed', '<iframe src="https://maps.google.com"></iframe>')
        ->call('updateContact')
        ->assertHasNoErrors();

    $contactSettings = app(ContactSettings::class);
    expect($contactSettings->phone_number)->toBe('0812 3456 7890');
    expect($contactSettings->email)->toBe('contact@example.com');
    expect($contactSettings->address)->toBe('Jl. Example No. 123, Jakarta');
});

it('cannot update contact settings without permission', function () {
    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('contactForm.phone_number', '081234567890')
        ->call('updateContact')
        ->assertForbidden();
});

// Social Settings Tests
it('shows validation error when social media url is invalid', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('socialForm.facebook', 'not-a-url')
        ->call('updateSocial')
        ->assertHasErrors([
            'socialForm.facebook' => 'url',
        ]);
});

it('shows validation error when social media url is too long', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('socialForm.instagram', 'https://instagram.com/'.str_repeat('a', 300))
        ->call('updateSocial')
        ->assertHasErrors([
            'socialForm.instagram' => 'max',
        ]);
});

it('can update social settings successfully', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('socialForm.facebook', 'https://facebook.com/example')
        ->set('socialForm.instagram', 'https://instagram.com/example')
        ->set('socialForm.youtube', 'https://youtube.com/example')
        ->set('socialForm.tiktok', 'https://tiktok.com/@example')
        ->set('socialForm.whatsapp', 'https://wa.me/6281234567890')
        ->set('socialForm.telegram', 'https://t.me/example')
        ->call('updateSocial')
        ->assertHasNoErrors();

    $socialSettings = app(SocialSettings::class);
    expect($socialSettings->facebook)->toBe('https://facebook.com/example');
    expect($socialSettings->instagram)->toBe('https://instagram.com/example');
    expect($socialSettings->youtube)->toBe('https://youtube.com/example');
});

it('can update social settings with null values', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('socialForm.facebook', null)
        ->set('socialForm.instagram', null)
        ->set('socialForm.youtube', null)
        ->call('updateSocial')
        ->assertHasNoErrors();

    $socialSettings = app(SocialSettings::class);
    expect($socialSettings->facebook)->toBeNull();
    expect($socialSettings->instagram)->toBeNull();
});

it('cannot update social settings without permission', function () {
    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('socialForm.facebook', 'https://facebook.com/example')
        ->call('updateSocial')
        ->assertForbidden();
});

// SEO Settings Tests
it('shows validation errors when updating seo settings with empty required fields', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.meta_description', '')
        ->set('seoForm.meta_keywords', '')
        ->set('seoForm.meta_author', '')
        ->call('updateSeo')
        ->assertHasErrors([
            'seoForm.meta_description' => 'required',
            'seoForm.meta_keywords' => 'required',
            'seoForm.meta_author' => 'required',
        ]);
});

it('shows validation error when meta description is too short', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.meta_description', 'Short')
        ->call('updateSeo')
        ->assertHasErrors([
            'seoForm.meta_description' => 'min',
        ]);
});

it('shows validation error when meta description is too long', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.meta_description', str_repeat('a', 161))
        ->call('updateSeo')
        ->assertHasErrors([
            'seoForm.meta_description' => 'max',
        ]);
});

it('shows validation error when og_type is invalid', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.og_type', 'invalid')
        ->call('updateSeo')
        ->assertHasErrors([
            'seoForm.og_type' => 'in',
        ]);
});

it('shows validation error when twitter_card is invalid', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.twitter_card', 'invalid')
        ->call('updateSeo')
        ->assertHasErrors([
            'seoForm.twitter_card' => 'in',
        ]);
});

it('shows validation error when og_image is not a valid url', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.og_image', 'not-a-url')
        ->call('updateSeo')
        ->assertHasErrors([
            'seoForm.og_image' => 'url',
        ]);
});

it('can update seo settings successfully', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.meta_description', 'This is a meta description for SEO purposes')
        ->set('seoForm.meta_keywords', 'parfum, fragrance, perfume')
        ->set('seoForm.meta_author', 'Example Author')
        ->set('seoForm.og_image', 'https://example.com/image.jpg')
        ->set('seoForm.og_title', 'Example Title')
        ->set('seoForm.og_description', 'Example OG Description')
        ->set('seoForm.og_type', 'website')
        ->set('seoForm.twitter_card', 'summary')
        ->set('seoForm.canonical_url', 'https://example.com')
        ->call('updateSeo')
        ->assertHasNoErrors();

    $seoSettings = app(SeoSettings::class);
    expect($seoSettings->meta_description)->toBe('This is a meta description for SEO purposes');
    expect($seoSettings->meta_keywords)->toBe('parfum, fragrance, perfume');
    expect($seoSettings->meta_author)->toBe('Example Author');
    expect($seoSettings->og_type)->toBe('website');
    expect($seoSettings->twitter_card)->toBe('summary');
});

it('can update seo settings with nullable fields as null', function () {
    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.meta_description', 'Valid meta description here')
        ->set('seoForm.meta_keywords', 'keyword1, keyword2')
        ->set('seoForm.meta_author', 'Author Name')
        ->set('seoForm.og_image', null)
        ->set('seoForm.og_title', null)
        ->set('seoForm.og_description', null)
        ->call('updateSeo')
        ->assertHasNoErrors();

    $seoSettings = app(SeoSettings::class);
    expect($seoSettings->og_image)->toBeNull();
    expect($seoSettings->og_title)->toBeNull();
});

it('cannot update seo settings without permission', function () {
    $this->user->roles()->detach();
    $this->user->permissions()->detach();

    Livewire::actingAs($this->user)
        ->test(Application::class)
        ->set('seoForm.meta_description', 'New description')
        ->call('updateSeo')
        ->assertForbidden();
});
