<?php

namespace Licenzo\Model;

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

use Licenzo\Casts\MoneyCast;
use Licenzo\Framework\Database\Model;
use Licenzo\Services\Integrations\ProviderAliasService;
use Licenzo\Traits\QueryBuilder\HasSearch;

/**
 * Customer Model
 *
 * Represents chat customers (both WordPress users and guests)
 */
class Customer extends Model
{
    use HasSearch;

    protected $searchables = [
        'email',
        'first_name',
        'last_name'
    ];

    // Ensure computed attributes are included in API responses
    protected $appends = [];

    /**
     * Table name
     */
    protected $table = 'licenzo_customers';

    /**
     * Primary key
     */
    protected $primaryKey = 'id';

    /**
     * Fillable attributes
     */
    protected $fillable = [
        'user_id',
        'provider',
        'provider_id',
        'email',
        'first_name',
        'last_name',
        'ip',
        'settings',
    ];

    /**
     * Attributes that should be cast
     */
    protected $casts = [
        'id'         => 'int',
        'user_id'    => 'int',
        'provider'   => 'string',
        'provider_id'=> 'string',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    public function setProviderAttribute($value)
    {
        $this->attributes['provider'] = ProviderAliasService::normalize((string) $value, 'manual');
    }


    /**
     * Get the WordPress user associated with this customer
     * Application-side relationship
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Accessor for settings — handles both JSON and serialized formats.
     */
    public function getSettingsAttribute()
    {
        $raw = $this->attributes['settings'] ?? null;

        if ($raw === null || $raw === '') {
            return [];
        }

        // Try JSON decode first (preferred format)
        $decoded = json_decode($raw, true);
        if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
            return $decoded;
        }

        // Fallback to unserialization for legacy data
        return maybe_unserialize($raw);
    }

    /**
     * Mutator for settings — always stores as JSON.
     */
    public function setSettingsAttribute($value)
    {
        $this->attributes['settings'] = is_string($value) ? $value : wp_json_encode($value);
    }

    public function subscriptions()
    {
        return $this->hasMany(Subscription::class);
    }

    public function transactions()
    {
        return $this->hasMany(SubscriptionTransaction::class);
    }

    public function invoices()
    {
        return $this->hasMany(Invoice::class);
    }

    public function idempotencyKeys()
    {
        return $this->hasMany(IdempotencyKey::class);
    }

    public function getLifetimeValueAttribute()
    {
        // Uses default 2-decimal factor; cross-currency aggregation requires per-currency grouping
        $factor = (int) pow(10, MoneyCast::minorUnits('USD'));
        $totalPaid = (int) $this->subscriptions()->sum('total_paid') / $factor;
        $totalRefunded = (int) $this->subscriptions()->sum('total_refunded') / $factor;

        return $totalPaid - $totalRefunded;
    }

    public function getLastPaymentDateAttribute()
    {
        return $this->transactions()->latest()->first()->created_at ?? null;
    }

    public function licenses()
    {
        return $this->hasMany(License::class);
    }

    /**
     * Get all license products through licenses
     *
     * Customer → License → LicenseProduct
     *
     * This returns LicenseProduct models (pivot records) that belong to this customer's licenses
     */
    public function products()
    {
        return $this->hasManyThrough( LicenseProduct::class, License::class, 'customer_id','license_id');
    }

    public function activities()
    {
        return $this->hasManyThrough( LicenseActivation::class, License::class, 'customer_id','license_id');
    }
}
