<?php

namespace App\Models;

use App\Helpers\ExpenseDocumentSettings;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;

class Expense extends Model
{
    protected $fillable = [
        'company_id', 'vendor_id', 'customer_id', 'category',
        'expense_number', 'expense_prefix', 'expense_seq',
        'expense_date', 'payment_method', 'reference_no', 'paid_to',
        'status', 'place_of_supply', 'is_igst', 'tax_on',
        'subtotal', 'taxable_amount', 'discount_amount', 'amount',
        'shipping_charges', 'discount_on_total', 'discount_all_percent',
        'discount_all_type', 'discount_all_value', 'custom_amount', 'custom_amount_label',
        'total_tax', 'cgst_amount', 'sgst_amount', 'igst_amount',
        'grand_total', 'round_off',
        'has_shipping', 'has_discount_total', 'has_discount_all',
        'has_custom_amount', 'has_total_quantity',
        'total_quantity_unit', 'total_quantity', 'show_cess', 'reverse_charge', 'shipping_mode',
        'notes', 'terms', 'private_notes', 'share_token',
    ];

    protected $casts = [
        'expense_date' => 'date',
        'amount' => 'decimal:2',
        'grand_total' => 'decimal:2',
        'round_off' => 'decimal:2',
        'total_tax' => 'decimal:2',
        'total_quantity' => 'decimal:3',
        'has_shipping' => 'boolean',
        'has_discount_total' => 'boolean',
        'has_discount_all' => 'boolean',
        'has_custom_amount' => 'boolean',
        'has_total_quantity' => 'boolean',
        'show_cess' => 'boolean',
        'reverse_charge' => 'boolean',
        'is_igst' => 'boolean',
    ];

    public function vendor(): BelongsTo
    {
        return $this->belongsTo(Vendor::class);
    }

    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    public function items(): HasMany
    {
        return $this->hasMany(ExpenseItem::class)->orderBy('id');
    }

    public function partyName(): string
    {
        return $this->vendor?->name ?? $this->paid_to ?? '—';
    }

    public function displayCategory(): string
    {
        if ($this->category) {
            return $this->category;
        }

        return $this->items->first()?->item_name ?? '—';
    }

    public function paymentMethodLabel(): string
    {
        return config('expense.payment_methods.'.$this->payment_method, ucfirst($this->payment_method ?? ''));
    }

    public function statusMeta(): array
    {
        return config('expense.statuses.'.$this->status, config('expense.statuses.draft'));
    }

    public function scopeForCompany(Builder $query, int $companyId): Builder
    {
        return $query->where('company_id', $companyId);
    }

    public function ensureShareToken(): string
    {
        if ($this->share_token) {
            return $this->share_token;
        }

        do {
            $token = Str::lower(Str::random(40));
        } while (static::where('share_token', $token)->exists());

        $this->forceFill(['share_token' => $token])->save();

        return $token;
    }

    public function publicShareUrl(): string
    {
        return route('public.expenses.show', $this->ensureShareToken());
    }

    public function typeLabel(): string
    {
        return ExpenseDocumentSettings::title($this->company_id);
    }
}
