<?php

namespace Tests\Unit\Models;

use Illuminate\Database\Eloquent\Model;
use App\Models\Plan;
use Tests\TestCase;

class PlanTest extends TestCase
{
    public $planData;
    protected function setUp(): void
    {
        parent::setUp();

        $this->planData = [
            'name' => 'Premium Plan',
            'description' => 'A premium subscription plan',
            'product_id' => 'prod_123456',
            'pricing_id' => 'price_123456',
            'shoppy_product_id' => 'shoppy_123456',
            'accept_stripe' => true,
            'accept_shoppy' => true,
            'oxapay_link' => 'https://oxapay.com/pay/123456',
            'accept_oxapay' => true,
            'price' => 9.99,
            'mailbox_limit' => 100,
            'monthly_billing' => true,
            'details' => [
                'feature1' => 'Unlimited emails',
                'feature2' => 'Priority support',
                'feature3' => 'Advanced features',
            ],
        ];
    }

    /** @test */
    public function it_can_create_a_plan_with_factory(): void
    {
        $plan = Plan::factory()->create();

        $this->assertInstanceOf(Plan::class, $plan);
        $this->assertIsString($plan->name);
        $this->assertIsFloat($plan->price);
    }

    /** @test */
    public function it_has_correct_fillable_attributes(): void
    {
        $plan = Plan::query()->create($this->planData);

        foreach ($this->planData as $key => $value) {
            $this->assertEquals($value, $plan->$key);
        }
    }

    /** @test */
    public function it_casts_details_to_json(): void
    {
        $details = [
            'feature1' => 'Unlimited emails',
            'feature2' => 'Priority support',
        ];

        $plan = Plan::factory()->create(['details' => $details]);

        $this->assertIsArray($plan->details);
        $this->assertEquals($details, $plan->details);
    }

    /** @test */
    public function it_casts_monthly_billing_to_boolean(): void
    {
        $plan1 = Plan::factory()->create(['monthly_billing' => true]);
        $plan2 = Plan::factory()->create(['monthly_billing' => false]);

        $this->assertTrue($plan1->monthly_billing);
        $this->assertFalse($plan2->monthly_billing);
        $this->assertIsBool($plan1->monthly_billing);
        $this->assertIsBool($plan2->monthly_billing);
    }

    /** @test */
    public function it_accepts_different_payment_methods(): void
    {
        $plan = Plan::factory()->create([
            'accept_stripe' => true,
            'accept_shoppy' => false,
            'accept_oxapay' => true,
        ]);

        $this->assertTrue($plan->accept_stripe);
        $this->assertFalse($plan->accept_shoppy);
        $this->assertTrue($plan->accept_oxapay);
    }

    /** @test */
    public function it_stores_monetary_values_correctly(): void
    {
        $plan = Plan::factory()->create([
            'price' => 19.99,
        ]);

        $this->assertIsFloat($plan->price);
        $this->assertEquals(19.99, $plan->price);
    }

    /** @test */
    public function it_stores_mailbox_limit_as_integer(): void
    {
        $plan = Plan::factory()->create([
            'mailbox_limit' => 50,
        ]);

        $this->assertIsInt($plan->mailbox_limit);
        $this->assertEquals(50, $plan->mailbox_limit);
    }

    /** @test */
    public function it_can_update_plan_attributes(): void
    {
        $plan = Plan::factory()->create();

        $plan->update([
            'name' => 'Updated Plan',
            'price' => 29.99,
            'monthly_billing' => false,
        ]);

        $plan->refresh();

        $this->assertEquals('Updated Plan', $plan->name);
        $this->assertEquals(29.99, $plan->price);
        $this->assertFalse($plan->monthly_billing);
    }

    /** @test */
    public function it_uses_correct_table_name(): void
    {
        $plan = new Plan;

        $this->assertEquals('plans', $plan->getTable());
    }

    /** @test */
    public function it_extends_model_class(): void
    {
        $plan = new Plan;

        $this->assertInstanceOf(Model::class, $plan);
    }
}
