<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseTransactions;
use Mtc\Core\Admin\User as AdminUser;
use Mtc\Modules\Members\Models\Member;
use Mtc\Plugins\WeightVerification\Src\Models\WeightVerification;
use Mtc\Plugins\WeightVerification\Src\WeightVerificationService;
use Mtc\Shop\Item;
use Mtc\Shop\Order;
use Mtc\Shop\Order\Item as OrderItem;
use Tests\TestCase;

class WeightVerificationServiceTest extends TestCase
{
    use DatabaseTransactions;

    private WeightVerificationService $service;

    protected function setUp(): void
    {
        parent::setUp();
        $this->service = app(WeightVerificationService::class);
    }

    /* ---------- Trigger: OrderPaid → pending verification ---------- */

    public function test_paid_order_with_flagged_item_creates_a_pending_verification(): void
    {
        $member = Member::factory()->create();
        $order = $this->orderWithItem($member, $this->makeItem(true));

        $verification = $this->service->handleOrderPaid($order->id);

        $this->assertNotNull($verification);
        $this->assertSame(WeightVerification::STATUS_PENDING, $verification->status);
        $this->assertDatabaseHas('weight_verifications', [
            'order_id' => $order->id,
            'member_id' => $member->id,
            'status' => WeightVerification::STATUS_PENDING,
        ]);
    }

    public function test_paid_order_without_a_flagged_item_creates_nothing(): void
    {
        $member = Member::factory()->create();
        $order = $this->orderWithItem($member, $this->makeItem(false));

        $this->assertNull($this->service->handleOrderPaid($order->id));
        $this->assertDatabaseMissing('weight_verifications', ['order_id' => $order->id]);
    }

    public function test_handle_order_paid_is_idempotent(): void
    {
        $member = Member::factory()->create();
        $order = $this->orderWithItem($member, $this->makeItem(true));

        $this->service->handleOrderPaid($order->id);
        $this->service->handleOrderPaid($order->id);

        $this->assertSame(1, WeightVerification::query()->where('order_id', $order->id)->count());
    }

    /* ---------- Approval gating ---------- */

    public function test_approval_is_blocked_until_photos_are_submitted(): void
    {
        $cases = [
            WeightVerification::STATUS_PENDING => true,
            WeightVerification::STATUS_RESUBMIT_REQUIRED => true,
            WeightVerification::STATUS_SUBMITTED => false,
            WeightVerification::STATUS_APPROVED => false,
        ];

        $orderId = 990100;
        foreach ($cases as $status => $expectedBlocked) {
            $orderId++;
            WeightVerification::query()->create([
                'order_id' => $orderId,
                'member_id' => 1,
                'status' => $status,
            ]);

            $this->assertSame(
                $expectedBlocked,
                $this->service->approvalBlockedForOrder($orderId),
                "status {$status} should " . ($expectedBlocked ? 'block' : 'allow') . ' approval'
            );
        }
    }

    public function test_orders_without_a_verification_are_never_blocked(): void
    {
        $this->assertFalse($this->service->approvalBlockedForOrder(990999));
    }

    /* ---------- Review outcomes ---------- */

    public function test_mark_approved_sets_status_and_reviewer(): void
    {
        $admin = AdminUser::factory()->create();
        $verification = WeightVerification::query()->create([
            'order_id' => 990200,
            'member_id' => 1,
            'status' => WeightVerification::STATUS_SUBMITTED,
        ]);

        $this->service->markApproved($verification, $admin);
        $verification->refresh();

        $this->assertSame(WeightVerification::STATUS_APPROVED, $verification->status);
        $this->assertSame($admin->id, $verification->reviewed_by);
        $this->assertNotNull($verification->reviewed_at);
    }

    public function test_request_resubmission_reopens_and_messages_the_patient(): void
    {
        $member = Member::factory()->create();
        $admin = AdminUser::factory()->create();
        $verification = WeightVerification::query()->create([
            'order_id' => 990300,
            'member_id' => $member->id,
            'status' => WeightVerification::STATUS_SUBMITTED,
            'front_file_id' => 1,
            'side_file_id' => 2,
        ]);

        $this->service->requestResubmission($verification, $admin, 'Photos too blurry, please retake.');
        $verification->refresh();

        // Re-opens the tab and records the decline. (The patient messaging itself
        // is delegated to the existing MembersMessaging system and is verified
        // through the end-to-end walkthrough rather than this isolated unit.)
        $this->assertSame(WeightVerification::STATUS_RESUBMIT_REQUIRED, $verification->status);
        $this->assertTrue($verification->action_required);
        $this->assertSame('Photos too blurry, please retake.', $verification->decline_reason);
        $this->assertSame($admin->id, $verification->reviewed_by);
        $this->assertNotNull($verification->reviewed_at);
    }

    /* ---------- Helpers ---------- */

    private function makeItem(bool $flagged): Item
    {
        return Item::query()->create([
            'name' => 'WV Test Item',
            'product_type' => 'doctor',
            'requires_weight_verification' => $flagged ? 1 : 0,
        ]);
    }

    private function orderWithItem(Member $member, Item $item): Order
    {
        $order = Order::factory()->create(['member' => $member->id]);
        // Replace the factory's random line items with a single controlled one.
        $order->items()->delete();
        OrderItem::factory()->for($order, 'order')->create([
            'item_id' => $item->id,
            'item_name' => $item->name,
        ]);

        return $order;
    }
}
