<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'member_id',
        'name',
        'email',
        'phone',
        'password',
        'user_type',
        'status',
        'created_by',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    /**
     * Get the member associated with the user.
     */
    public function member()
    {
        return $this->belongsTo(Member::class, 'member_id', 'member_id');
    }

    /**
     * Check if user is admin.
     */
    public function isAdmin()
    {
        return $this->user_type == 'admin';
    }

    /**
     * Check if user is committee member.
     */
    public function isCommittee()
    {
        return $this->user_type == 'committee';
    }

    /**
     * Check if user is regular member.
     */
    public function isMember()
    {
        return $this->user_type == 'member';
    }

    /**
     * Get the user type in Bangla.
     */
    public function getUserTypeInBanglaAttribute()
    {
        $types = [
            'admin' => 'অ্যাডমিন',
            'committee' => 'কমিটি',
            'member' => 'সদস্য',
            'staff' => 'স্টাফ'
        ];
        
        return $types[$this->user_type] ?? $this->user_type;
    }
    
    // Accessor: স্ট্যাটাস বাংলায়
    public function getStatusInBanglaAttribute()
    {
        $statuses = [
            'active' => 'সক্রিয়',
            'inactive' => 'নিষ্ক্রিয়',
            'suspended' => 'স্থগিত'
        ];
        
        return $statuses[$this->status] ?? $this->status;
    }

    // Scope: সক্রিয় ইউজার
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    // Scope: নির্দিষ্ট টাইপের ইউজার
    public function scopeType($query, $type)
    {
        return $query->where('user_type', $type);
    }

    // Scope: কমিটি সদস্য
    public function scopeCommittee($query)
    {
        return $query->where('user_type', 'committee');
    }

    // Scope: সাধারণ সদস্য
    public function scopeMember($query)
    {
        return $query->where('user_type', 'member');
    }

    // Method: ইউজারের সকল পারমিশন চেক
    public function hasPermission($permission)
    {
        // কমিটির জন্য সব পারমিশন
        if ($this->user_type === 'committee' || $this->user_type === 'admin') {
            return true;
        }
        
        // সদস্যের জন্য সীমিত পারমিশন
        $memberPermissions = [
            'view_profile',
            'edit_profile',
            'view_savings',
            'view_loans',
            'apply_loan',
            'view_notices',
            'view_events'
        ];
        
        return in_array($permission, $memberPermissions);
    }

    // নোটিশ সম্পর্কিত মেথড
    /**
     * Check if user has read a specific notice.
     */
    public function hasReadNotice($noticeId)
    {
        return $this->noticeReaders()->where('notice_id', $noticeId)->whereNotNull('read_at')->exists();
    }

    /**
     * Get all notice readings for this user.
     */
    public function noticeReaders()
    {
        return $this->hasMany(NoticeReader::class);
    }

    /**
     * Mark a notice as read for this user.
     */
    public function markNoticeAsRead($noticeId)
    {
        return $this->noticeReaders()->updateOrCreate(
            ['notice_id' => $noticeId],
            ['read_at' => now()]
        );
    }

    /**
     * Get all notices that this user has read.
     */
    public function readNotices()
    {
        return $this->belongsToMany(Notice::class, 'notice_readers')
                    ->withPivot('read_at')
                    ->withTimestamps()
                    ->whereNotNull('notice_readers.read_at');
    }

    /**
     * Get all unread notices for this user.
     */
    public function unreadNotices()
    {
        $readNoticeIds = $this->noticeReaders()->whereNotNull('read_at')->pluck('notice_id');
        
        return Notice::where('status', 'published')
            ->where(function($query) {
                $query->whereNull('expiry_date')
                      ->orWhere('expiry_date', '>=', now());
            })
            ->where(function($query) {
                // Check target audience
                $query->where('target_audience', 'all')
                      ->orWhere(function($q) {
                          if ($this->isCommittee()) {
                              $q->where('target_audience', 'committee');
                          }
                      })
                      ->orWhere(function($q) {
                          if ($this->isMember() && $this->member && $this->member->status == 'active') {
                              $q->where('target_audience', 'active_members');
                          }
                      })
                      ->orWhere(function($q) {
                          if ($this->member) {
                              $q->where('target_audience', 'specific')
                                ->whereJsonContains('specific_members', $this->member->id);
                          }
                      });
            })
            ->whereNotIn('id', $readNoticeIds)
            ->orderBy('publish_date', 'desc');
    }

    /**
     * Get important notices count for this user.
     */
    public function getUnreadImportantNoticesCountAttribute()
    {
        $readNoticeIds = $this->noticeReaders()->whereNotNull('read_at')->pluck('notice_id');
        
        return Notice::where('status', 'published')
            ->where('is_important', true)
            ->where(function($query) {
                $query->whereNull('expiry_date')
                      ->orWhere('expiry_date', '>=', now());
            })
            ->where(function($query) {
                // Check target audience
                $query->where('target_audience', 'all')
                      ->orWhere(function($q) {
                          if ($this->isCommittee()) {
                              $q->where('target_audience', 'committee');
                          }
                      })
                      ->orWhere(function($q) {
                          if ($this->isMember() && $this->member && $this->member->status == 'active') {
                              $q->where('target_audience', 'active_members');
                          }
                      })
                      ->orWhere(function($q) {
                          if ($this->member) {
                              $q->where('target_audience', 'specific')
                                ->whereJsonContains('specific_members', $this->member->id);
                          }
                      });
            })
            ->whereNotIn('id', $readNoticeIds)
            ->count();
    }

    /**
     * Get unread meeting notices count for this user.
     */
    public function getUnreadMeetingNoticesCountAttribute()
    {
        $readNoticeIds = $this->noticeReaders()->whereNotNull('read_at')->pluck('notice_id');
        
        return Notice::where('status', 'published')
            ->where('notice_type', 'meeting')
            ->where(function($query) {
                $query->whereNull('expiry_date')
                      ->orWhere('expiry_date', '>=', now());
            })
            ->where(function($query) {
                // Check target audience
                $query->where('target_audience', 'all')
                      ->orWhere(function($q) {
                          if ($this->isCommittee()) {
                              $q->where('target_audience', 'committee');
                          }
                      })
                      ->orWhere(function($q) {
                          if ($this->isMember() && $this->member && $this->member->status == 'active') {
                              $q->where('target_audience', 'active_members');
                          }
                      })
                      ->orWhere(function($q) {
                          if ($this->member) {
                              $q->where('target_audience', 'specific')
                                ->whereJsonContains('specific_members', $this->member->id);
                          }
                      });
            })
            ->whereNotIn('id', $readNoticeIds)
            ->count();
    }

    /**
     * Get dashboard statistics for the user.
     */
    public function getDashboardStats()
    {
        $stats = [];
        
        if ($this->isAdmin() || $this->isCommittee()) {
            // Admin/Committee statistics
            $stats['total_members'] = Member::count();
            $stats['active_members'] = Member::where('status', 'active')->count();
            $stats['pending_members'] = Member::where('approval_status', 'pending')->count();
            $stats['total_savings'] = \App\Models\MonthlySaving::where('status', 'paid')->sum('amount');
            $stats['total_loans'] = \App\Models\Loan::count();
            $stats['active_loans'] = \App\Models\Loan::where('status', 'active')->count();
            $stats['overdue_loans'] = \App\Models\Loan::where('status', 'overdue')->count();
            $stats['total_notices'] = Notice::count();
            $stats['unpublished_notices'] = Notice::where('status', 'draft')->count();
        } else {
            // Regular member statistics
            if ($this->member) {
                $stats['total_savings'] = $this->member->monthlySavings()->where('status', 'paid')->sum('amount');
                $stats['total_months'] = $this->member->monthlySavings()->where('status', 'paid')->count();
                $stats['active_loans'] = $this->member->loans()->where('status', 'active')->count();
                $stats['overdue_loans'] = $this->member->loans()->where('status', 'overdue')->count();
                $stats['next_meeting'] = \App\Models\Meeting::where('date', '>=', now())
                    ->where('status', 'scheduled')
                    ->orderBy('date', 'asc')
                    ->first();
            }
        }
        
        // Unread notices for all users
        $stats['unread_notices'] = $this->unreadNotices()->count();
        $stats['unread_important_notices'] = $this->unreadImportantNoticesCount;
        $stats['unread_meeting_notices'] = $this->unreadMeetingNoticesCount;
        
        return $stats;
    }

    /**
     * Check if the user can access a specific module.
     */
    public function canAccess($module)
    {
        $accessMatrix = [
            'admin' => [
                'members' => true,
                'loans' => true,
                'savings' => true,
                'incomes' => true,
                'expenses' => true,
                'committees' => true,
                'meetings' => true,
                'notices' => true,
                'events' => true,
                'reports' => true,
                'settings' => true,
                'users' => true,
            ],
            'committee' => [
                'members' => true,
                'loans' => true,
                'savings' => true,
                'incomes' => true,
                'expenses' => true,
                'committees' => true,
                'meetings' => true,
                'notices' => true,
                'events' => true,
                'reports' => true,
                'settings' => false,
                'users' => false,
            ],
            'member' => [
                'members' => false,
                'loans' => true,
                'savings' => true,
                'incomes' => false,
                'expenses' => false,
                'committees' => false,
                'meetings' => true,
                'notices' => true,
                'events' => true,
                'reports' => true,
                'settings' => false,
                'users' => false,
            ],
        ];
        
        return $accessMatrix[$this->user_type][$module] ?? false;
    }

    /**
     * Get user's role permissions.
     */
    public function getPermissionsAttribute()
    {
        $permissions = [
            'can_manage_members' => $this->isAdmin() || $this->isCommittee(),
            'can_manage_loans' => $this->isAdmin() || $this->isCommittee(),
            'can_manage_savings' => $this->isAdmin() || $this->isCommittee(),
            'can_manage_finances' => $this->isAdmin() || $this->isCommittee(),
            'can_manage_committees' => $this->isAdmin() || $this->isCommittee(),
            'can_manage_meetings' => $this->isAdmin() || $this->isCommittee(),
            'can_manage_notices' => $this->isAdmin() || $this->isCommittee(),
            'can_manage_events' => $this->isAdmin() || $this->isCommittee(),
            'can_view_reports' => true,
            'can_manage_settings' => $this->isAdmin(),
            'can_manage_users' => $this->isAdmin(),
        ];
        
        return $permissions;
    }

    /**
     * Check if user can manage a specific notice.
     */
    public function canManageNotice($notice = null)
    {
        // Admin can manage all notices
        if ($this->isAdmin()) {
            return true;
        }
        
        // Committee can manage notices
        if ($this->isCommittee()) {
            return true;
        }
        
        // Regular members cannot manage notices
        if ($this->isMember()) {
            return false;
        }
        
        // Check specific notice ownership
        if ($notice) {
            return $notice->created_by == $this->id;
        }
        
        return false;
    }
    /**
 * Get the monthly savings for the member.
 */
    public function monthlySavings()
    {
        return $this->hasMany(MonthlySaving::class, 'member_id', 'member_id');
    }

/**
 * Get the loans for the member.
 */
    public function loans()
    {
        return $this->hasMany(Loan::class, 'member_id', 'member_id');
    }

/**
 * Get the user account associated with the member.
 */
    public function user()
    {
        return $this->hasOne(User::class, 'member_id', 'member_id');
    }
}