<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
use Illuminate\Database\Eloquent\Factories\HasFactory;

class Account extends Model
{
    use LogsActivity, SoftDeletes;

    protected $table = 'accounts';

    protected $fillable = [
        'chart_of_account_id',
        'sub_chart_of_account_id',
        'uom_id',
        'name',
        'code',
        'description',
        'balance',
        'is_active',
        'model_type',
        'is_shop_item',
        'model_id',
        // Item-specific fields
        'sku',
        // 'type',
        'barcode',
        'reorder_level',
        'status',
        'unit_of_measure',
        // Customer-specific fields
        'email',
        'phone',
        'address',
        'tax_number',
        'opening_balance',
        'pay_term_no',
        'pay_term_type',
        'credit_limit',
        'commission_rate',
        'security_deposit',
        'is_security_account',
        // Supplier-specific fields
        'supplier_code',
        'contact_person',
        'payment_terms',
        'credit_rating',
        'notes',
        // Employee-specific fields
        'gender',
        'employee_type',
        'wage_type',
        'basic_salary',
        'daily_wage',
        'contract_amount',
        'working_hours',
        'holidays_per_week',
        'allow_login',
        'username',
        'password',
        'shop_id',
        'department_name',
        'department_id',
        'team_name',
        'team_id',
        'work_category',
        // Shop-specific fields
        'city',
        // Item-specific fields
        'weighted_average_price',
        'price',
    ];

    protected $casts = [
        'chart_of_account_id' => 'integer',
        'uom_id' => 'integer',
        'balance' => 'decimal:2',
        'is_active' => 'boolean',
        'is_shop_item' => 'boolean',
        'model_id' => 'integer',
        'reorder_level' => 'decimal:6',
        'opening_balance' => 'decimal:4',
        'credit_limit' => 'decimal:4',
        'commission_rate' => 'decimal:2',
        'security_deposit' => 'decimal:2',
        'is_security_account' => 'boolean',
        'pay_term_no' => 'integer',
        'credit_rating' => 'decimal:1',
        // Employee casts
        'basic_salary' => 'decimal:2',
        'daily_wage' => 'decimal:2',
        'contract_amount' => 'decimal:2',
        'working_hours' => 'integer',
        'holidays_per_week' => 'integer',
        'allow_login' => 'boolean',
        'shop_id' => 'integer',
        'weighted_average_price' => 'decimal:4',
    ];

    // Relationships
    public function chartOfAccount(): BelongsTo
    {
        return $this->belongsTo(ChartOfAccount::class, 'chart_of_account_id');
    }

    public function subChartOfAccount(): BelongsTo
    {
        return $this->belongsTo(ChartOfAccount::class, 'sub_chart_of_account_id');
    }

    public function uom(): BelongsTo
    {
        return $this->belongsTo(Uom::class, 'uom_id', 'id');
    }

    public function contact(): BelongsTo
    {
        return $this->belongsTo(Contact::class, 'model_id')->where('model_type', 'contact');
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'model_id')->where('model_type', 'user');
    }

    public function model()
    {
        if ($this->model_type === 'contact') {
            return $this->belongsTo(Contact::class, 'model_id');
        } elseif ($this->model_type === 'user') {
            return $this->belongsTo(User::class, 'model_id');
        } elseif ($this->model_type === 'Item') {
            // For items, return a relationship to self since model_id references the same account
            return $this->belongsTo(Account::class, 'model_id');
        }

        // Return a dummy relationship to avoid null return
        return $this->belongsTo(Account::class, 'model_id')->whereRaw('1 = 0');
    }

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

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

    public function shopProducts(): HasMany
    {
        return $this->hasMany(ShopProduct::class, 'account_id');
    }

    public function shop(): BelongsTo
    {
        // For shop accounts, return self-reference since we're using Account model
        if ($this->model_type === 'shop') {
            return $this->belongsTo(Account::class, 'model_id');
        }

        // Return a dummy relationship to avoid null return
        return $this->belongsTo(Account::class, 'model_id')->whereRaw('1 = 0');
    }
    public function bom()
    {
        return $this->belongsTo(ManufacturingBOM::class, 'id','finished_goods_account_id');
    }

    // Employee relationships
    public function attendances(): HasMany
    {
        return $this->hasMany(EmployeeAttendance::class, 'employee_id');
    }

    public function payrolls(): HasMany
    {
        return $this->hasMany(EmployeePayroll::class, 'employee_id');
    }

    public function incentives(): HasMany
    {
        return $this->hasMany(Incentive::class, 'employee_id');
    }
    // Scopes
    public function scopeForContact($query, $contactId)
    {
        return $query->where('model_type', 'App\Models\Contact')->where('model_id', $contactId);
    }

    public function scopeForUser($query, $userId)
    {
        return $query->where('model_type', 'App\Models\User')->where('model_id', $userId);
    }

    public function scopeByModelType($query, $modelType)
    {
        return $query->where('model_type', $modelType);
    }

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

    public function scopeItems($query)
    {
        return $query->where('model_type', 'Item');
    }

    public function scopeByType($query, $type)
    {
        return $query->where('type', $type);
    }

    public function scopeByCategory($query, $categoryId)
    {
        return $query->where('chart_of_account_id', $categoryId);
    }

    // Helper methods
    public function getTotalDebitsAttribute()
    {
        return $this->transactions()
                    ->where('transaction_type', 'debit')
                    ->sum('amount');
    }

    public function getTotalCreditsAttribute()
    {
        return $this->transactions()
                    ->where('transaction_type', 'credit')
                    ->sum('amount');
    }

    public function getBalanceAttribute()
    {
        // Calculate balance based on chart of account type
        // Positive balance means the account owes money (for customers = amount to receive, for suppliers = amount to pay)
        $chartAccountType = $this->chartOfAccount?->type;

        switch ($chartAccountType) {
            case 'asset':
                // Assets: Debits increase, Credits decrease
                return $this->total_debits - $this->total_credits;

            case 'liability':
            case 'equity':
            case 'income':
                // Liabilities/Equity/Income: Credits increase, Debits decrease
                return $this->total_credits - $this->total_debits;

            case 'expense':
                // Expenses: Debits increase, Credits decrease
                return $this->total_debits - $this->total_credits;

            default:
                // Fallback: assume asset account behavior
                return $this->total_debits - $this->total_credits;
        }
    }

    public function getFormattedBalanceAttribute()
    {
        return format_currency($this->balance);
    }

    public function getFormattedTotalDebitsAttribute()
    {
        return format_currency($this->total_debits);
    }

    public function getFormattedTotalCreditsAttribute()
    {
        return format_currency($this->total_credits);
    }

    public function getModelNameAttribute()
    {
        return $this->model ? $this->model->name : 'Unknown';
    }

    public function getModelTypeLabelAttribute()
    {
        return class_basename($this->model_type);
    }

    public function getChartOfAccountNameAttribute()
    {
        return $this->chartOfAccount ? $this->chartOfAccount->name : 'Unknown';
    }

    // Item-specific helper methods (when model_type = 'Item')
    public function getTypeLabelAttribute()
    {
        if ($this->model_type !== 'Item') return null;
        return ucwords(str_replace('_', ' ', $this->type));
    }

    public function isLinked(): bool
    {
        if ($this->model_type !== 'Item') return false;

        // Check if item is linked in any transactional records
        return \App\Models\PurchaseRequestItem::where('item_id', $this->id)->exists()
            || \App\Models\PurchaseOrderItem::where('item_id', $this->id)->exists()
            || \App\Models\QcItem::where('item_id', $this->id)->exists();
    }

    public function getLinkedModules(): array
    {
        if ($this->model_type !== 'Item') return [];

        $modules = [];
        if (\App\Models\PurchaseRequestItem::where('item_id', $this->id)->exists()) $modules[] = 'Purchase Requests';
        if (\App\Models\PurchaseOrderItem::where('item_id', $this->id)->exists()) $modules[] = 'Purchase Orders';
        if (\App\Models\QcItem::where('item_id', $this->id)->exists()) $modules[] = 'QCs';
        return $modules;
    }

    public function canDelete(): bool
    {
        if ($this->model_type !== 'Item') return true;
        return !$this->isLinked();
    }

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->useLogName('account')
            ->logFillable()
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs();
    }
    
}
