<?php

namespace Tests\Traits;

use Carbon\Carbon;
use Modules\AccountingCore\App\Models\BasicTransaction;
use Modules\AccountingCore\App\Models\BasicTransactionCategory;
use Modules\AccountingCore\App\Models\TaxRate;

/**
 * Trait for creating AccountingCore entities in tests.
 */
trait CreatesAccountingCoreEntities
{
    /**
     * Create a basic transaction category.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createTransactionCategory(array $attributes = []): BasicTransactionCategory
    {
        $userId = $attributes['created_by_id'] ?? auth()->id() ?? 1;

        return BasicTransactionCategory::create(array_merge([
            'name' => 'Test Category '.uniqid(),
            'type' => 'income',
            'icon' => 'bx bx-dollar',
            'color' => '#28a745',
            'is_active' => true,
            'created_by_id' => $userId,
        ], $attributes));
    }

    /**
     * Create an income category.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createIncomeCategory(array $attributes = []): BasicTransactionCategory
    {
        return $this->createTransactionCategory(array_merge([
            'type' => 'income',
            'name' => 'Income Category '.uniqid(),
        ], $attributes));
    }

    /**
     * Create an expense category.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createExpenseCategory(array $attributes = []): BasicTransactionCategory
    {
        return $this->createTransactionCategory(array_merge([
            'type' => 'expense',
            'name' => 'Expense Category '.uniqid(),
            'icon' => 'bx bx-minus-circle',
            'color' => '#dc3545',
        ], $attributes));
    }

    /**
     * Create a basic transaction.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createBasicTransaction(array $attributes = []): BasicTransaction
    {
        $userId = $attributes['created_by_id'] ?? auth()->id() ?? 1;

        // Create category if not provided
        if (! isset($attributes['category_id'])) {
            $type = $attributes['type'] ?? 'income';
            $category = $type === 'income'
                ? $this->createIncomeCategory(['created_by_id' => $userId])
                : $this->createExpenseCategory(['created_by_id' => $userId]);
            $attributes['category_id'] = $category->id;
        }

        return BasicTransaction::create(array_merge([
            'type' => 'income',
            'amount' => 1000.00,
            'description' => 'Test Transaction '.uniqid(),
            'transaction_date' => now(),
            'reference_number' => 'REF'.strtoupper(uniqid()),
            'payment_method' => 'cash',
            'created_by_id' => $userId,
        ], $attributes));
    }

    /**
     * Create an income transaction.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createIncomeTransaction(array $attributes = []): BasicTransaction
    {
        return $this->createBasicTransaction(array_merge([
            'type' => 'income',
        ], $attributes));
    }

    /**
     * Create an expense transaction.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createExpenseTransaction(array $attributes = []): BasicTransaction
    {
        return $this->createBasicTransaction(array_merge([
            'type' => 'expense',
        ], $attributes));
    }

    /**
     * Create a transaction for a specific date.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createTransactionForDate(Carbon $date, array $attributes = []): BasicTransaction
    {
        return $this->createBasicTransaction(array_merge([
            'transaction_date' => $date,
        ], $attributes));
    }

    /**
     * Create a tax rate.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createTaxRate(array $attributes = []): TaxRate
    {
        $userId = $attributes['created_by_id'] ?? auth()->id() ?? 1;

        return TaxRate::create(array_merge([
            'name' => 'Tax Rate '.uniqid(),
            'rate' => 5.00,
            'type' => 'percentage',
            'is_default' => false,
            'is_active' => true,
            'description' => 'Test tax rate',
            'tax_authority' => 'Test Authority',
            'created_by_id' => $userId,
        ], $attributes));
    }

    /**
     * Create a percentage tax rate.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createPercentageTaxRate(float $rate = 10.00, array $attributes = []): TaxRate
    {
        return $this->createTaxRate(array_merge([
            'rate' => $rate,
            'type' => 'percentage',
            'name' => "Tax {$rate}%",
        ], $attributes));
    }

    /**
     * Create a fixed tax rate.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createFixedTaxRate(float $rate = 100.00, array $attributes = []): TaxRate
    {
        return $this->createTaxRate(array_merge([
            'rate' => $rate,
            'type' => 'fixed',
            'name' => "Fixed Tax {$rate}",
        ], $attributes));
    }

    /**
     * Create a default tax rate.
     *
     * @param  array<string, mixed>  $attributes
     */
    protected function createDefaultTaxRate(array $attributes = []): TaxRate
    {
        // Unset any existing defaults first
        TaxRate::where('is_default', true)->update(['is_default' => false]);

        return $this->createTaxRate(array_merge([
            'is_default' => true,
            'name' => 'Default Tax Rate',
        ], $attributes));
    }
}
