<?php

namespace App\Models;

use App\Helpers\CreditNoteDocumentSettings;
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 CreditNote extends Model
{
    protected $fillable = [
        'company_id', 'customer_id', 'invoice_id',
        'credit_note_number', 'credit_note_prefix', 'credit_note_seq',
        'credit_note_date', 'related_invoice_number', 'related_invoice_date',
        'reason', 'restore_stock', 'status',
        'place_of_supply', 'is_igst', 'tax_on',
        'subtotal', 'taxable_amount', 'discount_amount',
        'shipping_charges', 'discount_on_total', 'discount_all_percent',
        'discount_all_type', 'discount_all_value', 'custom_amount', 'custom_amount_label',
        'advance_payment', 'has_shipping', 'has_discount_total', 'has_discount_all',
        'has_custom_amount', 'has_advance_payment', 'has_total_quantity',
        'total_quantity_unit', 'total_quantity', 'show_cess', 'shipping_mode',
        'total_tax', 'cgst_amount', 'sgst_amount', 'igst_amount',
        'round_off', 'grand_total', 'credits_available',
        'notes', 'terms', 'private_notes', 'share_token',
    ];

    protected $casts = [
        'credit_note_date' => 'date',
        'related_invoice_date' => 'date',
        'grand_total' => 'decimal:2',
        'credits_available' => 'decimal:2',
        'round_off' => 'decimal:2',
        'total_tax' => 'decimal:2',
        'total_quantity' => 'decimal:3',
        'restore_stock' => 'boolean',
        'has_shipping' => 'boolean',
        'has_discount_total' => 'boolean',
        'has_discount_all' => 'boolean',
        'has_custom_amount' => 'boolean',
        'has_advance_payment' => 'boolean',
        'has_total_quantity' => 'boolean',
        'show_cess' => 'boolean',
        'is_igst' => 'boolean',
    ];

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

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

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

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

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

    public function reasonLabel(): string
    {
        return config('credit_note.reasons.'.$this->reason, $this->reason);
    }

    public function displayInvoiceNumber(): ?string
    {
        if ($this->invoice_id && $this->relationLoaded('invoice') && $this->invoice) {
            return $this->invoice->invoice_number;
        }

        return $this->related_invoice_number;
    }

    public function displayInvoiceDate(): ?\Illuminate\Support\Carbon
    {
        if ($this->invoice_id && $this->relationLoaded('invoice') && $this->invoice?->invoice_date) {
            return $this->invoice->invoice_date;
        }

        return $this->related_invoice_date;
    }

    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.credit-notes.show', $this->ensureShareToken());
    }
}
