<?php

namespace App\Models;

use App\Enums\InvoiceStatus;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;

class Invoice extends Model
{
    use HasFactory;

    protected $fillable = [
        'customer_id',
        'internal_id',
        'status',
        'subtotal',
        'total',
        'gst',
        'pst',
        'date',
    ];

    protected $appends = [
        'gst_amount',
        'pst_amount',
    ];

    protected $casts = [
        'date'     => 'datetime',
        'total'    => 'decimal:2',
        'subtotal' => 'decimal:2',
        'status'   => InvoiceStatus::class,
    ];

    public static function boot(): void
    {
        parent::boot();

        static::created(function ($model) {
            $model->attributes['internal_id'] = $model->generateInternalId($model->id);
            $model->save();
        });
    }

    public function setStatus(InvoiceStatus $status)
    {
        if ($this->status !== $status) {
            $this->status = $status;
            $this->save();
        }
    }

    public function generateInternalId(int $id): string
    {
        $po   = str_pad(strval($id), 4, '0', STR_PAD_LEFT);
        $year = date('y');

        return 'TN-IN-'.$year.'-'.$po;
    }

    public function calculateTotals(): void
    {
        $subtotal = 0;

        foreach ($this->orders as $order) {
            $subtotal += $order->total_service_price;
        }

        $this->subtotal = $subtotal;
        $this->total    = $subtotal + $this->gst_amount + $this->pst_amount;

        $this->save();
    }

    public function getGstAmountAttribute(): float
    {
        if ($this->gst) {
            return number_format($this->subtotal * 0.05, 2);
        }

        return 0.00;
    }

    public function getPstAmountAttribute(): float
    {
        if ($this->pst) {
            return number_format($this->subtotal * 0.07, 2);
        }

        return 0.00;
    }

    public function orders(): HasMany
    {
        return $this->HasMany(Order::class);
    }

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

    public function productServices(): HasManyThrough
    {
        return $this->hasManyThrough(ProductService::class, Order::class);
    }
}