<?php

namespace Tests\Feature;

use App\Http\Controllers\Admin\OrderController;
use App\Order;
use App\User;
use App\UserCard;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;

class AdminOrderCancellationFeeTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->createCancellationFeeTables();
    }

    public function testCancellationFeeRequiresCancelledOrder(): void
    {
        $user = $this->createUser(['payjp_customer_id' => 'cus_test']);
        $order = $this->createOrder($user->id, ['status' => Order::STATUS_PROCESSING]);

        $response = $this->chargeCancellationFee($order->id, ['amount' => 5000]);

        $this->assertSame(422, $response->getStatusCode());
        $this->assertSame(
            'キャンセル済みの注文のみキャンセル料を請求できます。',
            $response->getData(true)['errors']
        );
    }

    public function testCancellationFeeRequiresPayjpCustomer(): void
    {
        $user = $this->createUser(['payjp_customer_id' => null]);
        $order = $this->createOrder($user->id, ['status' => Order::STATUS_CANCELLED]);

        $response = $this->chargeCancellationFee($order->id, ['amount' => 5000]);

        $this->assertSame(422, $response->getStatusCode());
        $this->assertSame(
            '登録済みクレジットカードがありません。',
            $response->getData(true)['errors']
        );
    }

    public function testCancellationFeeRequiresVerifiedDefaultCard(): void
    {
        $user = $this->createUser(['payjp_customer_id' => 'cus_test']);
        $order = $this->createOrder($user->id, ['status' => Order::STATUS_CANCELLED]);
        UserCard::create([
            'user_id' => $user->id,
            'payjp_card_id' => 'car_test',
            'is_default' => 1,
            'is_activated' => 1,
            'is_deleted' => 0,
            'payjp_three_d_secure_status' => 'unverified',
        ]);

        $response = $this->chargeCancellationFee($order->id, ['amount' => 5000]);

        $this->assertSame(422, $response->getStatusCode());
        $this->assertSame(
            '3Dセキュア認証済みのデフォルトカードがありません。',
            $response->getData(true)['errors']
        );
    }

    private function chargeCancellationFee(int $orderId, array $payload)
    {
        $request = Request::create('/api/admin/order/' . $orderId . '/cancellation-fee', 'POST', $payload);

        return (new OrderController())->chargeCancellationFee($request, $orderId);
    }

    private function createUser(array $attributes = []): User
    {
        return User::create(array_merge([
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => bcrypt('password'),
            'is_activated' => 1,
            'is_deleted' => 0,
        ], $attributes));
    }

    private function createOrder(int $userId, array $attributes = []): Order
    {
        return Order::create(array_merge([
            'code' => 'ORD-TEST',
            'user_id' => $userId,
            'status' => Order::STATUS_CANCELLED,
            'total_price' => 0,
            'is_activated' => 1,
            'is_deleted' => 0,
        ], $attributes));
    }

    private function createCancellationFeeTables(): void
    {
        Schema::dropIfExists('user_payment_histories');
        Schema::dropIfExists('payments');
        Schema::dropIfExists('user_cards');
        Schema::dropIfExists('orders');
        Schema::dropIfExists('users');

        Schema::create('users', function ($table) {
            $table->id();
            $table->string('name')->nullable();
            $table->string('username')->nullable();
            $table->string('email')->unique();
            $table->string('password')->nullable();
            $table->string('payjp_customer_id')->nullable();
            $table->boolean('is_activated')->default(true);
            $table->boolean('is_deleted')->default(false);
            $table->timestamps();
        });

        Schema::create('orders', function ($table) {
            $table->id();
            $table->string('code')->nullable();
            $table->unsignedBigInteger('user_id')->nullable();
            $table->integer('status')->default(Order::STATUS_NEW);
            $table->integer('total_price')->default(0);
            $table->boolean('is_activated')->default(true);
            $table->boolean('is_deleted')->default(false);
            $table->timestamps();
        });

        Schema::create('user_cards', function ($table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->string('payjp_card_id')->nullable();
            $table->boolean('is_default')->default(false);
            $table->boolean('is_activated')->default(true);
            $table->boolean('is_deleted')->default(false);
            $table->string('payjp_three_d_secure_status')->nullable();
            $table->timestamps();
        });

        Schema::create('payments', function ($table) {
            $table->id();
            $table->unsignedBigInteger('order_id')->nullable();
            $table->string('code')->nullable();
            $table->integer('total')->default(0);
            $table->timestamps();
        });

        Schema::create('user_payment_histories', function ($table) {
            $table->id();
            $table->unsignedBigInteger('user_id')->nullable();
            $table->unsignedBigInteger('order_id')->nullable();
            $table->unsignedBigInteger('payment_id')->nullable();
            $table->integer('amount')->default(0);
            $table->integer('payment_status')->default(0);
            $table->text('note')->nullable();
            $table->timestamps();
        });
    }
}
