<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;

class TaxRate extends Model
{
    protected $fillable = [
        'company_id', 'name', 'rate', 'has_surcharge', 'surcharge_rate',
        'type', 'is_group', 'is_selectable', 'is_active',
    ];

    protected $casts = [
        'rate' => 'decimal:2',
        'surcharge_rate' => 'decimal:2',
        'has_surcharge' => 'boolean',
        'is_group' => 'boolean',
        'is_selectable' => 'boolean',
        'is_active' => 'boolean',
    ];

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

    public function groupMembers(): HasMany
    {
        return $this->hasMany(TaxGroupMember::class, 'tax_group_id')->orderBy('sort_order');
    }

    public function members(): BelongsToMany
    {
        return $this->belongsToMany(
            TaxRate::class,
            'tax_group_members',
            'tax_group_id',
            'tax_rate_id'
        )->withPivot('sort_order')->orderByPivot('sort_order');
    }

    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    public function scopeSelectable($query)
    {
        return $query->where('is_selectable', true);
    }

    public function scopeIndividuals($query)
    {
        return $query->where('is_group', false);
    }

    public function scopeGroups($query)
    {
        return $query->where('is_group', true);
    }

    public function listDisplayName(): string
    {
        if (! $this->is_group) {
            return $this->name;
        }

        $this->loadMissing('members');
        $memberNames = $this->members->pluck('name')->filter()->join(', ');

        return $memberNames !== ''
            ? "{$this->name} ({$memberNames})"
            : $this->name;
    }

    public function surchargeDisplay(): ?string
    {
        if (! $this->is_group && $this->has_surcharge && $this->surcharge_rate !== null) {
            return rtrim(rtrim(number_format((float) $this->surcharge_rate, 2), '0'), '.').'%';
        }

        return null;
    }

    public function percentDisplay(): string
    {
        return rtrim(rtrim(number_format((float) $this->rate, 2), '0'), '.').'%';
    }

    public static function syncGroupRate(TaxRate $group): void
    {
        if (! $group->is_group) {
            return;
        }

        $group->load('members');
        $group->update([
            'rate' => $group->members->sum(fn (TaxRate $tax) => (float) $tax->rate),
        ]);
    }
}
