<?php

namespace Tests\Feature;

use App\Models\Central\Company;
use App\Models\Central\Plan;
use App\Models\Tenant\OnlineOrder;
use App\Models\Tenant\Part;
use App\Models\Tenant\PartCrossRef;
use App\Models\Tenant\Warehouse;
use App\Models\Tenant\WarehouseEvent;
use App\Services\Warehouse\WarehouseService;
use App\Tenancy\TenantManager;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class OnlineStoreTest extends TestCase
{
    use RefreshDatabase;

    public function test_catalog_404_when_shop_disabled(): void
    {
        $this->makeShop('shopoff', enabled: false);
        $this->get('http://shopoff.service.mir.md/shop')->assertNotFound();
    }

    public function test_catalog_lists_published_parts_only(): void
    {
        $ctx = $this->makeShop('shopon', enabled: true);
        Part::create(['name' => 'Filtru public', 'sell_price' => 100, 'qty' => 5, 'unit' => 'buc', 'is_active' => true, 'is_published' => true]);
        Part::create(['name' => 'Filtru privat', 'sell_price' => 100, 'qty' => 5, 'unit' => 'buc', 'is_active' => true, 'is_published' => false]);

        $resp = $this->get('http://shopon.service.mir.md/shop');
        $resp->assertOk();
        $resp->assertSee('Filtru public');
        $resp->assertDontSee('Filtru privat');
    }

    public function test_search_matches_cross_reference(): void
    {
        $ctx = $this->makeShop('shopcross', enabled: true);
        $part = Part::create(['name' => 'Filtru ulei', 'article' => 'OEM-1', 'sell_price' => 50, 'qty' => 3, 'unit' => 'buc', 'is_active' => true, 'is_published' => true]);
        PartCrossRef::create(['part_id' => $part->id, 'cross_article' => 'W811-80', 'brand' => 'MANN']);

        // searchPublished should find the part by its cross article.
        $found = Part::searchPublished('W811-80')->get();
        $this->assertCount(1, $found);
        $this->assertEquals($part->id, $found->first()->id);
    }

    public function test_place_order_creates_order_with_token_and_items(): void
    {
        $ctx = $this->makeShop('shopbuy', enabled: true);
        $part = Part::create(['name' => 'Plăcuțe frână', 'sell_price' => 200, 'qty' => 10, 'unit' => 'buc', 'is_active' => true, 'is_published' => true]);

        $base = 'http://shopbuy.service.mir.md/shop';

        // Add to cart (session persists across requests in the same test).
        $this->post("$base/part/{$part->id}/add", ['qty' => 2])->assertRedirect();

        $resp = $this->post("$base/checkout", [
            'customer_name' => 'Ion Pop',
            'customer_phone' => '+37369123456',
            'customer_email' => 'ion@example.com',
            'delivery_method' => 'pickup',
        ]);
        $resp->assertRedirect();

        $order = OnlineOrder::first();
        $this->assertNotNull($order);
        $this->assertEquals('Ion Pop', $order->customer_name);
        $this->assertNotEmpty($order->tracking_token);
        $this->assertEquals(400.0, (float) $order->total);   // 2 × 200, pickup = no fee
        $this->assertEquals(1, $order->items()->count());

        // Confirmation page reachable by token.
        $this->get($order->trackingUrl())->assertOk()->assertSee($order->number);
    }

    public function test_fulfill_issues_stock_via_warehouse(): void
    {
        $ctx = $this->makeShop('shopfulfill', enabled: true);
        $svc = app(WarehouseService::class);
        $part = Part::create(['name' => 'Amortizor', 'sell_price' => 500, 'qty' => 0, 'unit' => 'buc', 'is_active' => true, 'is_published' => true]);
        $svc->receive($part, 10, 300.0);

        $order = OnlineOrder::create([
            'number' => OnlineOrder::generateNumber($ctx['company']->id),
            'customer_name' => 'X', 'customer_phone' => '+37360000000',
            'delivery_method' => 'pickup', 'status' => 'new',
        ]);
        $order->items()->create([
            'company_id' => $ctx['company']->id,
            'part_id' => $part->id,
            'name' => $part->name, 'qty' => 3, 'price' => 500,
        ]);

        // Simulate the fulfill action body.
        $svc->issue($part, 3, null, $order, 'test');
        $part->refresh();

        $this->assertEquals(7.0, (float) $part->qty);
        $this->assertEquals(1, WarehouseEvent::where('part_id', $part->id)->where('type', 'issue')->count());
    }

    public function test_order_token_isolated_across_tenants(): void
    {
        $a = $this->makeShop('shopa', enabled: true);
        $partA = Part::create(['name' => 'P', 'sell_price' => 10, 'qty' => 1, 'unit' => 'buc', 'is_active' => true, 'is_published' => true]);
        $orderA = OnlineOrder::create([
            'number' => OnlineOrder::generateNumber($a['company']->id),
            'customer_name' => 'A', 'customer_phone' => '1', 'delivery_method' => 'pickup', 'status' => 'new',
        ]);

        $this->makeShop('shopb', enabled: true);

        // Tenant B cannot view tenant A's order token.
        $this->get('http://shopb.service.mir.md/order/' . $orderA->tracking_token)->assertNotFound();
    }

    private function makeShop(string $slug, bool $enabled): array
    {
        $plan = Plan::firstOrCreate(['slug' => 'test'], ['name' => 'T', 'price' => 0, 'features' => []]);
        $company = Company::create([
            'plan_id' => $plan->id,
            'slug' => $slug,
            'name' => ucfirst($slug),
            'status' => 'active',
            'settings' => ['shop' => ['enabled' => $enabled, 'delivery_methods' => ['pickup', 'courier'], 'delivery_fee' => 50, 'free_delivery_over' => 1000]],
        ]);
        app(TenantManager::class)->setCurrent($company);

        $wh = Warehouse::create(['code' => 'MAIN', 'name' => 'D', 'is_default' => true, 'is_active' => true]);
        $company->forceFill(['default_warehouse_id' => $wh->id])->saveQuietly();

        return compact('company', 'wh');
    }
}
