<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Carbon\Carbon;

class Expense extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * টেবিলের নাম নির্ধারণ (যদি টেবিলের নাম 'expenses' না হয়)
     */
    protected $table = 'expenses';

    /**
     * ম্যাস অ্যাসাইনমেন্টের জন্য অনুমোদিত কলাম
     */
    protected $fillable = [
        'title',
        'description',
        'amount',
        'category_id',
        'user_id',
        'expense_date',
        'payment_method',
        'reference_no',
        'receipt_attachment',
        'notes',
        'status',
        'approved_by',
        'approved_at',
        'rejection_reason',
        'voucher_number',
        'paid_to'
    ];

    /**
     * ডাটা টাইপ কাস্টিং
     */
    protected $casts = [
        'amount' => 'decimal:2',
        'expense_date' => 'date',
        'approved_at' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * ডিফল্ট অ্যাট্রিবিউট ভ্যালু
     */
    protected $attributes = [
        'status' => 'pending',
    ];

    /**
     * বুট মেথড - ইভেন্ট হ্যান্ডলার
     */
    protected static function boot()
    {
        parent::boot();
        
        static::creating(function ($expense) {
            // ভাউচার নম্বর জেনারেট
            if (empty($expense->voucher_number)) {
                $expense->voucher_number = self::generateVoucherNumber();
            }
            
            // expense_date সেট (যদি না থাকে)
            if (empty($expense->expense_date)) {
                $expense->expense_date = now();
            }
            
            // স্ট্যাটাস সেট (যদি না থাকে)
            if (empty($expense->status)) {
                $expense->status = 'pending';
            }
        });

        static::updating(function ($expense) {
            // যদি স্ট্যাটাস approved হয় এবং approved_at না থাকে
            if ($expense->status == 'approved' && empty($expense->approved_at)) {
                $expense->approved_at = now();
            }
        });

        static::deleting(function ($expense) {
            // ডিলিটের আগে অ্যাটাচমেন্ট ডিলিট করুন
            if ($expense->receipt_attachment && \Storage::disk('public')->exists($expense->receipt_attachment)) {
                \Storage::disk('public')->delete($expense->receipt_attachment);
            }
        });
    }

    /**
     * ভাউচার নম্বর জেনারেট
     */
    public static function generateVoucherNumber()
    {
        $prefix = 'EXP';
        $year = date('Y');
        $month = date('m');
        
        $lastExpense = self::whereYear('created_at', $year)
            ->whereMonth('created_at', $month)
            ->orderBy('id', 'desc')
            ->first();
        
        if ($lastExpense && $lastExpense->voucher_number) {
            $parts = explode('-', $lastExpense->voucher_number);
            $lastNumber = (int)end($parts);
            $newNumber = $lastNumber + 1;
        } else {
            $newNumber = 1;
        }
        
        return $prefix . '-' . $year . $month . '-' . str_pad($newNumber, 3, '0', STR_PAD_LEFT);
    }

    /**
     * Accessor - date কলামের জন্য backward compatibility
     */
    public function getDateAttribute()
    {
        return $this->expense_date ?? $this->created_at;
    }

    /**
     * সম্পর্ক: ক্যাটাগরি
     */
    public function category()
    {
        return $this->belongsTo(ExpenseCategory::class, 'category_id')->withDefault([
            'name' => 'N/A',
            'name_bn' => 'N/A'
        ]);
    }

    /**
     * সম্পর্ক: ইউজার (সৃষ্টিকর্তা)
     */
    public function user()
    {
        return $this->belongsTo(User::class, 'user_id')->withDefault([
            'name' => 'N/A',
            'name_bn' => 'N/A'
        ]);
    }

    /**
     * সম্পর্ক: অনুমোদনকারী
     */
    public function approver()
    {
        return $this->belongsTo(User::class, 'approved_by')->withDefault([
            'name' => 'N/A',
            'name_bn' => 'N/A'
        ]);
    }

    /**
     * পেমেন্ট মেথড লিস্ট
     */
    public static function getPaymentMethodList()
    {
        return [
            'cash' => 'নগদ',
            'bank' => 'ব্যাংক',
            'check' => 'চেক',
            'mobile_banking' => 'মোবাইল ব্যাংকিং'
        ];
    }

    /**
     * Accessor: পেমেন্ট মেথড বাংলায়
     */
    public function getPaymentMethodInBanglaAttribute()
    {
        $methods = self::getPaymentMethodList();
        return $methods[$this->payment_method] ?? $this->payment_method;
    }

    /**
     * স্ট্যাটাস লিস্ট
     */
    public static function getStatusList()
    {
        return [
            'pending' => 'অপেক্ষমাণ',
            'approved' => 'অনুমোদিত',
            'rejected' => 'বাতিল'
        ];
    }

    /**
     * Accessor: স্ট্যাটাস বাংলায়
     */
    public function getStatusInBanglaAttribute()
    {
        $statuses = self::getStatusList();
        return $statuses[$this->status] ?? $this->status;
    }

    /**
     * Accessor: পরিমাণ বাংলায় (সংখ্যায়)
     */
    public function getAmountInBanglaAttribute()
    {
        return $this->convertToBanglaNumber(number_format($this->amount, 2));
    }

    /**
     * Accessor: পরিমাণ কথায়
     */
    public function getAmountInWordsAttribute()
    {
        return $this->convertNumberToWords($this->amount);
    }

    /**
     * Accessor: মাস এবং বছর
     */
    public function getMonthYearAttribute()
    {
        if ($this->expense_date) {
            return Carbon::parse($this->expense_date)->format('F Y');
        }
        return 'N/A';
    }

    /**
     * Accessor: মাস এবং বছর বাংলায়
     */
    public function getMonthYearBanglaAttribute()
    {
        if (!$this->expense_date) {
            return 'N/A';
        }
        
        $date = Carbon::parse($this->expense_date);
        $monthEn = $date->format('F');
        $year = $date->format('Y');
        
        $months = [
            'January' => 'জানুয়ারি',
            'February' => 'ফেব্রুয়ারি',
            'March' => 'মার্চ',
            'April' => 'এপ্রিল',
            'May' => 'মে',
            'June' => 'জুন',
            'July' => 'জুলাই',
            'August' => 'আগস্ট',
            'September' => 'সেপ্টেম্বর',
            'October' => 'অক্টোবর',
            'November' => 'নভেম্বর',
            'December' => 'ডিসেম্বর'
        ];
        
        $monthBn = $months[$monthEn] ?? $monthEn;
        $yearBn = $this->convertToBanglaNumber($year);
        
        return $monthBn . ' ' . $yearBn;
    }

    /**
     * Accessor: তারিখ বাংলায়
     */
    public function getExpenseDateBanglaAttribute()
    {
        if (!$this->expense_date) {
            return 'তারিখ নেই';
        }
        
        try {
            $date = Carbon::parse($this->expense_date);
            $day = $date->format('d');
            $month = $date->format('m');
            $year = $date->format('Y');
            
            $banglaMonths = [
                '01' => 'জানুয়ারি', '02' => 'ফেব্রুয়ারি', '03' => 'মার্চ',
                '04' => 'এপ্রিল', '05' => 'মে', '06' => 'জুন',
                '07' => 'জুলাই', '08' => 'আগস্ট', '09' => 'সেপ্টেম্বর',
                '10' => 'অক্টোবর', '11' => 'নভেম্বর', '12' => 'ডিসেম্বর'
            ];
            
            $dayBn = $this->convertToBanglaNumber($day);
            $yearBn = $this->convertToBanglaNumber($year);
            
            return $dayBn . ' ' . ($banglaMonths[$month] ?? $month) . ' ' . $yearBn;
        } catch (\Exception $e) {
            return 'তারিখ নেই';
        }
    }

    /**
     * Accessor: রিসিট অ্যাটাচমেন্ট URL
     */
    public function getReceiptUrlAttribute()
    {
        if ($this->receipt_attachment && \Storage::disk('public')->exists($this->receipt_attachment)) {
            return asset('storage/' . $this->receipt_attachment);
        }
        return null;
    }

    /**
     * Accessor: রিসিট ফাইল নাম
     */
    public function getReceiptNameAttribute()
    {
        if ($this->receipt_attachment) {
            return basename($this->receipt_attachment);
        }
        return null;
    }

    /**
     * ইংরেজি সংখ্যা থেকে বাংলা সংখ্যায় রূপান্তর
     */
    public function convertToBanglaNumber($number)
    {
        $banglaDigits = ['০', '১', '২', '৩', '৪', '৫', '৬', '৭', '৮', '৯'];
        $englishDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
        
        return str_replace($englishDigits, $banglaDigits, (string)$number);
    }

    /**
     * সংখ্যা থেকে কথায় রূপান্তর
     */
    private function convertNumberToWords($number)
    {
        if ($number == 0) return 'শূন্য টাকা';
        
        $words = [];
        $number = round($number, 2);
        $taka = floor($number);
        $paisa = round(($number - $taka) * 100);
        
        if ($taka > 0) {
            $words[] = $this->convertTakaToWords($taka) . ' টাকা';
        }
        
        if ($paisa > 0) {
            $words[] = $this->convertTakaToWords($paisa) . ' পয়সা';
        }
        
        return implode(' ও ', $words) . ' মাত্র';
    }

    /**
     * টাকা কথায় রূপান্তর
     */
    private function convertTakaToWords($number)
    {
        $ones = [
            0 => '', 1 => 'এক', 2 => 'দুই', 3 => 'তিন', 4 => 'চার',
            5 => 'পাঁচ', 6 => 'ছয়', 7 => 'সাত', 8 => 'আট', 9 => 'নয়',
            10 => 'দশ', 11 => 'এগারো', 12 => 'বারো', 13 => 'তেরো',
            14 => 'চৌদ্দ', 15 => 'পনেরো', 16 => 'ষোল', 17 => 'সতেরো',
            18 => 'আঠারো', 19 => 'উনিশ', 20 => 'বিশ', 21 => 'একুশ',
            22 => 'বাইশ', 23 => 'তেইশ', 24 => 'চব্বিশ', 25 => 'পঁচিশ',
            26 => 'ছাব্বিশ', 27 => 'সাতাশ', 28 => 'আঠাশ', 29 => 'ঊনত্রিশ',
            30 => 'ত্রিশ', 31 => 'একত্রিশ', 32 => 'বত্রিশ', 33 => 'তেত্রিশ',
            34 => 'চৌত্রিশ', 35 => 'পঁয়ত্রিশ', 36 => 'ছত্রিশ', 37 => 'সাইত্রিশ',
            38 => 'আটত্রিশ', 39 => 'ঊনচল্লিশ', 40 => 'চল্লিশ', 41 => 'একচল্লিশ',
            42 => 'বিয়াল্লিশ', 43 => 'তেতাল্লিশ', 44 => 'চুয়াল্লিশ', 45 => 'পঁয়তাল্লিশ',
            46 => 'ছেচল্লিশ', 47 => 'সাতচল্লিশ', 48 => 'আটচল্লিশ', 49 => 'ঊনপঞ্চাশ',
            50 => 'পঞ্চাশ', 51 => 'একান্ন', 52 => 'বায়ান্ন', 53 => 'তিপ্পান্ন',
            54 => 'চুয়ান্ন', 55 => 'পঞ্চান্ন', 56 => 'ছাপ্পান্ন', 57 => 'সাতান্ন',
            58 => 'আটান্ন', 59 => 'ঊনষাট', 60 => 'ষাট', 61 => 'একষট্টি',
            62 => 'বাষট্টি', 63 => 'তেষট্টি', 64 => 'চৌষট্টি', 65 => 'পঁয়ষট্টি',
            66 => 'ছেষট্টি', 67 => 'সাতষট্টি', 68 => 'আটষট্টি', 69 => 'ঊনসত্তর',
            70 => 'সত্তর', 71 => 'একাত্তর', 72 => 'বাহাত্তর', 73 => 'তিয়াত্তর',
            74 => 'চুয়াত্তর', 75 => 'পঁচাত্তর', 76 => 'ছিয়াত্তর', 77 => 'সাতাত্তর',
            78 => 'আটাত্তর', 79 => 'ঊনআশি', 80 => 'আশি', 81 => 'একাশি',
            82 => 'বিরাশি', 83 => 'তিরাশি', 84 => 'চুরাশি', 85 => 'পঁচাশি',
            86 => 'ছিয়াশি', 87 => 'সাতাশি', 88 => 'আটাশি', 89 => 'ঊননব্বই',
            90 => 'নব্বই', 91 => 'একানব্বই', 92 => 'বিরানব্বই', 93 => 'তিরানব্বই',
            94 => 'চুরানব্বই', 95 => 'পঁচানব্বই', 96 => 'ছিয়ানব্বই', 97 => 'সাতানব্বই',
            98 => 'আটানব্বই', 99 => 'নিরানব্বই'
        ];
        
        if ($number < 100) {
            return $ones[$number];
        }
        
        if ($number < 1000) {
            $hundred = floor($number / 100);
            $remainder = $number % 100;
            $result = $ones[$hundred] . 'শ';
            if ($remainder > 0) {
                $result .= ' ' . $ones[$remainder];
            }
            return $result;
        }
        
        if ($number < 100000) {
            $thousand = floor($number / 1000);
            $remainder = $number % 1000;
            $result = $ones[$thousand] . ' হাজার';
            if ($remainder > 0) {
                $result .= ' ' . $this->convertTakaToWords($remainder);
            }
            return $result;
        }
        
        if ($number < 10000000) {
            $lakh = floor($number / 100000);
            $remainder = $number % 100000;
            $result = $ones[$lakh] . ' লক্ষ';
            if ($remainder > 0) {
                $result .= ' ' . $this->convertTakaToWords($remainder);
            }
            return $result;
        }
        
        $crore = floor($number / 10000000);
        $remainder = $number % 10000000;
        $result = $ones[$crore] . ' কোটি';
        if ($remainder > 0) {
            $result .= ' ' . $this->convertTakaToWords($remainder);
        }
        return $result;
    }

    /**
     * স্কোপ: অনুমোদিত
     */
    public function scopeApproved($query)
    {
        return $query->where('status', 'approved');
    }

    /**
     * স্কোপ: অপেক্ষমাণ
     */
    public function scopePending($query)
    {
        return $query->where('status', 'pending');
    }

    /**
     * স্কোপ: বাতিল
     */
    public function scopeRejected($query)
    {
        return $query->where('status', 'rejected');
    }

    /**
     * স্কোপ: আজকের
     */
    public function scopeToday($query)
    {
        return $query->whereDate('expense_date', Carbon::today());
    }

    /**
     * স্কোপ: এই মাসের
     */
    public function scopeThisMonth($query)
    {
        return $query->whereMonth('expense_date', now()->month)
                    ->whereYear('expense_date', now()->year);
    }

    /**
     * স্কোপ: গত মাসের
     */
    public function scopeLastMonth($query)
    {
        return $query->whereMonth('expense_date', now()->subMonth()->month)
                    ->whereYear('expense_date', now()->subMonth()->year);
    }

    /**
     * স্কোপ: এই বছরের
     */
    public function scopeThisYear($query)
    {
        return $query->whereYear('expense_date', now()->year);
    }

    /**
     * স্কোপ: তারিখ রেঞ্জ অনুযায়ী
     */
    public function scopeDateRange($query, $startDate, $endDate)
    {
        return $query->whereBetween('expense_date', [$startDate, $endDate]);
    }

    /**
     * স্কোপ: ক্যাটাগরি অনুযায়ী
     */
    public function scopeByCategory($query, $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }

    /**
     * স্কোপ: পেমেন্ট মেথড অনুযায়ী
     */
    public function scopeByPaymentMethod($query, $method)
    {
        return $query->where('payment_method', $method);
    }

    /**
     * স্কোপ: ইউজার অনুযায়ী
     */
    public function scopeByUser($query, $userId)
    {
        return $query->where('user_id', $userId);
    }

    /**
     * টোটাল অ্যামাউন্ট
     */
    public function scopeTotalAmount($query)
    {
        return $query->sum('amount');
    }

    /**
     * ক্যাটাগরি অনুযায়ী গ্রুপ
     */
    public function scopeGroupByCategory($query)
    {
        return $query->selectRaw('category_id, sum(amount) as total')
                    ->groupBy('category_id')
                    ->with('category');
    }

    /**
     * মাস অনুযায়ী গ্রুপ
     */
    public function scopeGroupByMonth($query, $year = null)
    {
        $year = $year ?? now()->year;
        
        return $query->selectRaw('MONTH(expense_date) as month, sum(amount) as total')
                    ->whereYear('expense_date', $year)
                    ->groupBy('month')
                    ->orderBy('month');
    }
}