<?php

namespace Database\Factories;

use App\Enums\OrderChannel;
use App\Enums\OrderStatus;
use App\Models\Customer;
use App\Models\Order;
use App\Models\Outlet;
use App\Models\User;
use App\Models\Voucher;
use Illuminate\Database\Eloquent\Factories\Factory;

class OrderFactory extends Factory
{
    protected $model = Order::class;

    public function definition(): array
    {
        $subtotal = $this->faker->numberBetween(50000, 1000000);
        $discount = $this->faker->numberBetween(0, (int) ($subtotal * 0.3)); // Max 30% discount
        $total = $subtotal - $discount;
        $cogs = (int) ($subtotal * 0.4); // COGS is typically 40% of subtotal

        // Generate invoice number: INV + YYYYMMDD + 4 digit sequence
        // For testing, use random sequence to ensure uniqueness
        $sequence = $this->faker->numberBetween(1, 9999);
        $invoiceNumber = 'INV'.now()->format('Ymd').str_pad($sequence, 4, '0', STR_PAD_LEFT);

        return [
            'outlet_id' => Outlet::factory(),
            'user_id' => User::factory(),
            'customer_id' => null,
            'voucher_id' => null,
            'invoice_number' => $invoiceNumber,
            'cogs' => $cogs,
            'subtotal' => $subtotal,
            'discount' => $discount,
            'total' => $total,
            'channel' => $this->faker->randomElement(OrderChannel::cases()),
            'status' => $this->faker->randomElement(OrderStatus::cases()),
            'ordered_at' => $this->faker->dateTimeBetween('-1 year', 'now'),
        ];
    }

    public function draft(): Factory
    {
        return $this->state(fn () => ['status' => OrderStatus::DRAFT]);
    }

    public function pending(): Factory
    {
        return $this->state(fn () => ['status' => OrderStatus::PENDING]);
    }

    public function partial(): Factory
    {
        return $this->state(fn () => ['status' => OrderStatus::PARTIAL]);
    }

    public function paid(): Factory
    {
        return $this->state(fn () => ['status' => OrderStatus::PAID]);
    }

    public function overdue(): Factory
    {
        return $this->state(fn () => ['status' => OrderStatus::OVERDUE]);
    }

    public function canceled(): Factory
    {
        return $this->state(fn () => ['status' => OrderStatus::CANCELED]);
    }

    public function outlet(): Factory
    {
        return $this->state(fn () => ['channel' => OrderChannel::OUTLET]);
    }

    public function shopee(): Factory
    {
        return $this->state(fn () => ['channel' => OrderChannel::SHOPEE]);
    }

    public function tokopedia(): Factory
    {
        return $this->state(fn () => ['channel' => OrderChannel::TOKOPEDIA]);
    }

    public function website(): Factory
    {
        return $this->state(fn () => ['channel' => OrderChannel::WEBSITE]);
    }

    public function instagram(): Factory
    {
        return $this->state(fn () => ['channel' => OrderChannel::INSTAGRAM]);
    }

    public function whatsapp(): Factory
    {
        return $this->state(fn () => ['channel' => OrderChannel::WHATSAPP]);
    }

    public function other(): Factory
    {
        return $this->state(fn () => ['channel' => OrderChannel::OTHER]);
    }

    public function withCustomer(?Customer $customer = null): Factory
    {
        return $this->state(fn () => ['customer_id' => $customer?->id ?? Customer::factory()]);
    }

    public function withVoucher(?Voucher $voucher = null): Factory
    {
        return $this->state(fn () => ['voucher_id' => $voucher?->id ?? Voucher::factory()]);
    }

    public function withOutlet(?Outlet $outlet = null): Factory
    {
        return $this->state(fn () => ['outlet_id' => $outlet?->id ?? Outlet::factory()]);
    }

    public function withUser(?User $user = null): Factory
    {
        return $this->state(fn () => ['user_id' => $user?->id ?? User::factory()]);
    }

    public function withAmounts(int $subtotal, ?int $discount = null, ?int $cogs = null): Factory
    {
        return $this->state(function (array $attributes) use ($subtotal, $discount, $cogs) {
            $discount = $discount ?? $this->faker->numberBetween(0, (int) ($subtotal * 0.3));
            $total = $subtotal - $discount;
            $cogs = $cogs ?? (int) ($subtotal * 0.4);

            return [
                'subtotal' => $subtotal,
                'discount' => $discount,
                'total' => $total,
                'cogs' => $cogs,
            ];
        });
    }

    public function withDiscount(int $discount): Factory
    {
        return $this->state(function (array $attributes) use ($discount) {
            $subtotal = $attributes['subtotal'] ?? $this->faker->numberBetween(50000, 1000000);
            $total = $subtotal - $discount;

            return [
                'discount' => $discount,
                'total' => max(0, $total),
            ];
        });
    }

    public function withoutDiscount(): Factory
    {
        return $this->state(function (array $attributes) {
            $subtotal = $attributes['subtotal'] ?? $this->faker->numberBetween(50000, 1000000);

            return [
                'discount' => 0,
                'total' => $subtotal,
            ];
        });
    }

    public function today(): Factory
    {
        return $this->state(fn () => [
            'ordered_at' => now(),
            'created_at' => now(),
        ]);
    }

    public function yesterday(): Factory
    {
        return $this->state(function () {
            $yesterday = now()->subDay();

            return [
                'ordered_at' => $yesterday,
                'created_at' => $yesterday,
            ];
        });
    }

    public function thisWeek(): Factory
    {
        return $this->state(fn () => ['ordered_at' => $this->faker->dateTimeBetween('-7 days', 'now')]);
    }

    public function thisMonth(): Factory
    {
        return $this->state(fn () => ['ordered_at' => $this->faker->dateTimeBetween('-30 days', 'now')]);
    }

    public function lastMonth(): Factory
    {
        return $this->state(fn () => ['ordered_at' => $this->faker->dateTimeBetween('-60 days', '-30 days')]);
    }
}
