<?php

namespace App\Models;

use App\Models\Traits\HasApproval;
use App\Models\Traits\HasAuditFields;
use App\Models\Traits\HasScopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class TaxInvoice extends Model
{
    use HasScopes, HasApproval, SoftDeletes, HasAuditFields;

    protected $table = 'tax_invoices';

    /**
     * Custom column mapping for traits
     */
    protected string $dateColumn = 'invoice_date';
    protected string $companyColumn = 'company_id';

    protected $fillable = [
        'invoice_no',
        'invoice_date',
        'delivery_note',
        'terms_payment',
        'reference_no',
        'other_reference',
        'company_id',
        'address',
        'gst',
        'phone',
        'email',
        'buyer_order_no',
        'reference_date',
        'dispatch_through',
        'destination',
        'vehicle_no',
        'terms_of_delivery',
        'taxable_value',
        'sgst',
        'cgst',
        'igst',
        'total_tax_amount',
        'total_amount',
        'amount_in_words',
        'status',
        'approved_by',
        'approved_at',
        'approval_remarks',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'invoice_date' => 'date',
        'reference_date' => 'date',
        'approved_at' => 'datetime',
        'taxable_value' => 'decimal:2',
        'sgst' => 'decimal:2',
        'cgst' => 'decimal:2',
        'igst' => 'decimal:2',
        'total_tax_amount' => 'decimal:2',
        'total_amount' => 'decimal:2',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    // ──────────────────────────────────────────────────────────────────────────
    // RELATIONSHIPS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Invoice line items
     */
    public function items()
    {
        return $this->hasMany(TaxInvoiceItem::class);
    }

    /**
     * Company (customer) for this invoice
     */
    public function company()
    {
        return $this->belongsTo(CustomerVendor::class, 'company_id');
    }

    /**
     * Payments received for this invoice
     */
    public function payments()
    {
        return $this->hasMany(SalesPayment::class, 'invoice_id');
    }

    /**
     * Credit notes for this invoice
     */
    public function creditNotes()
    {
        return $this->hasMany(SalesCreditNote::class, 'invoice_id');
    }

    // ──────────────────────────────────────────────────────────────────────────
    // SCOPES
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Filter unpaid invoices
     */
    public function scopeUnpaid(Builder $query): Builder
    {
        return $query->whereColumn('total_amount', '>', function ($q) {
            $q->selectRaw('COALESCE(SUM(amount), 0)')
              ->from('sales_payments')
              ->whereColumn('sales_payments.invoice_id', 'tax_invoices.id');
        });
    }

    /**
     * Filter paid invoices
     */
    public function scopePaid(Builder $query): Builder
    {
        return $query->whereExists(function ($q) {
            $q->selectRaw('1')
              ->from('sales_payments')
              ->whereColumn('sales_payments.invoice_id', 'tax_invoices.id')
              ->groupBy('invoice_id')
              ->havingRaw('SUM(amount) >= tax_invoices.total_amount');
        });
    }

    /**
     * Search by invoice number or company
     */
    public function scopeSearchInvoice(Builder $query, string $term): Builder
    {
        return $query->where(function ($q) use ($term) {
            $q->where('invoice_no', 'LIKE', "%{$term}%")
              ->orWhereHas('company', function ($cq) use ($term) {
                  $cq->where('company', 'LIKE', "%{$term}%");
              });
        });
    }

    /**
     * Filter by amount range
     */
    public function scopeAmountBetween(Builder $query, float $min, float $max): Builder
    {
        return $query->whereBetween('total_amount', [$min, $max]);
    }

    // ──────────────────────────────────────────────────────────────────────────
    // ACCESSORS & HELPERS
    // ──────────────────────────────────────────────────────────────────────────

    /**
     * Get total amount paid
     */
    public function getPaidAmount(): float
    {
        return $this->payments()->sum('payment_amount') ?? 0;
    }

    /**
     * Get total credit notes amount
     */
    public function getCreditNotesAmount(): float
    {
        return SalesCreditNote::where('invoice_no', $this->invoice_no)->sum('amount') ?? 0;
    }

    /**
     * Get total debit notes amount
     */
    public function getDebitNotesAmount(): float
    {
        return SalesDebitNote::where('invoice_no', $this->invoice_no)->sum('amount') ?? 0;
    }

    /**
     * Get outstanding balance
     * Formula: Invoice Amount + Debit Notes - Payments - Credit Notes
     */
    public function getBalance(): float
    {
        $invoiceAmount = $this->total_amount;
        $debitNotes = $this->getDebitNotesAmount();
        $payments = $this->getPaidAmount();
        $creditNotes = $this->getCreditNotesAmount();

        return $invoiceAmount + $debitNotes - $payments - $creditNotes;
    }

    /**
     * Check if fully paid
     */
    public function isFullyPaid(): bool
    {
        return $this->getBalance() <= 0;
    }

    /**
     * Get debit notes for this invoice
     */
    public function debitNotes()
    {
        return $this->hasMany(SalesDebitNote::class, 'invoice_no', 'invoice_no');
    }

    /**
     * Check if overdue (assuming 30 days payment terms if not specified)
     */
    public function isOverdue(): bool
    {
        if ($this->isFullyPaid()) {
            return false;
        }

        $dueDate = $this->invoice_date->addDays(30);
        return now()->greaterThan($dueDate);
    }

    /**
     * Get tax breakdown
     */
    public function getTaxBreakdown(): array
    {
        return [
            'taxable_value' => $this->taxable_value,
            'sgst' => $this->sgst,
            'cgst' => $this->cgst,
            'igst' => $this->igst,
            'total_tax' => $this->total_tax_amount,
        ];
    }
}
