<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;

class Owner extends Model
{
    /**
     * Company details used on owner statements.
     */
    public const COMPANY_LEGAL_NAME = 'Wilberforce Offroad Ltd T/A Dream Drives';
    public const COMPANY_GST_NUMBER = '131-424-418';

    protected $fillable = [
        'brand_id',
        'name',
        'email',
        'phone',

        // Legacy free-form field:
        'bank_account_details',

        'notes',

        // Structured fields for statements / payouts:
        'legal_name',
        'bank_account_name',
        'bank_account_number',
        'bank_reference',
        'payout_schedule',
        'cc_email',
        'gst_registered',
        'gst_number',
    ];

    protected $casts = [
        'gst_registered' => 'bool',
    ];

    public function vehicles(): HasMany
    {
        return $this->hasMany(Vehicle::class);
    }

    public function jobs(): HasManyThrough
    {
        // Assumes jobs.vehicle_id → vehicles.id
        return $this->hasManyThrough(
            Job::class,
            Vehicle::class,
            'owner_id',   // Foreign key on vehicles
            'vehicle_id', // Foreign key on jobs
            'id',         // Local key on owners
            'id',         // Local key on vehicles
        );
    }

    /**
     * Convenience helper for upcoming bookings for this owner's vehicles.
     */
    public function upcomingJobs(): HasManyThrough
    {
        // Swap "start_at" if your date column is named differently.
        return $this->jobs()
            ->where('start_at', '>=', now())
            ->orderBy('start_at');
    }

    public function ledgerEntries(): HasMany
    {
        return $this->hasMany(OwnerLedgerEntry::class);
    }

    public function payouts(): HasMany
    {
        return $this->hasMany(OwnerPayout::class);
    }

    /**
     * Earnings from all ledger entries of type "earning".
     * Uses preloaded withSum() value when available, falls back to a query.
     * Respects owner_share_cents overrides when set.
     */
    public function getEarningsCentsAttribute(): int
    {
        if (
            array_key_exists('earnings_cents', $this->attributes)
            && $this->attributes['earnings_cents'] !== null
        ) {
            return (int) $this->attributes['earnings_cents'];
        }

        return (int) $this->ledgerEntries()
            ->where('type', 'earning')
            ->get()
            ->sum(fn (OwnerLedgerEntry $entry) => $entry->effective_owner_share_cents);
    }

    /**
     * Costs from all ledger entries of type "cost".
     * (Always 100% to owner, so we sum the raw amount.)
     */
    public function getCostsCentsAttribute(): int
    {
        if (
            array_key_exists('costs_cents', $this->attributes)
            && $this->attributes['costs_cents'] !== null
        ) {
            return (int) $this->attributes['costs_cents'];
        }

        return (int) $this->ledgerEntries()
            ->where('type', 'cost')
            ->sum('amount_cents');
    }

    /**
     * Payouts from all ledger entries of type "payout".
     */
    public function getPayoutsCentsAttribute(): int
    {
        if (
            array_key_exists('payouts_cents', $this->attributes)
            && $this->attributes['payouts_cents'] !== null
        ) {
            return (int) $this->attributes['payouts_cents'];
        }

        return (int) $this->ledgerEntries()
            ->where('type', 'payout')
            ->sum('amount_cents');
    }

    /**
     * Adjustments from all ledger entries of type "adjustment".
     * Treated like earnings-style entries using effective owner share.
     */
    public function getAdjustmentsCentsAttribute(): int
    {
        if (
            array_key_exists('adjustments_cents', $this->attributes)
            && $this->attributes['adjustments_cents'] !== null
        ) {
            return (int) $this->attributes['adjustments_cents'];
        }

        return (int) $this->ledgerEntries()
            ->where('type', 'adjustment')
            ->get()
            ->sum(fn (OwnerLedgerEntry $entry) => $entry->effective_owner_share_cents);
    }

    /**
     * Balance = earnings + adjustments - costs - payouts.
     * Uses the accessor values above, which will use preloaded sums when present.
     */
    public function getBalanceCentsAttribute(): int
    {
        return $this->earnings_cents
            + $this->adjustments_cents
            - $this->costs_cents
            - $this->payouts_cents;
    }

    public function getBalanceFormattedAttribute(): string
    {
        return sprintf('$%0.2f', $this->balance_cents / 100);
    }
}
