<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Schema;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * Approval status constants.
     */
    const APPROVAL_PENDING = 'pending';
    const APPROVAL_APPROVED = 'approved';
    const APPROVAL_REJECTED = 'rejected';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'phone',
        'password',
        'device_id',
        'api_token',
        'session_token',
        'session_device_id',
        'last_active_at',
        'force_logout',
        'force_logout_reason',
        'is_active',
        'sms_service_enabled',
        'promotions_enabled',
        'created_by_admin',
        'managed_by_admin',
        'token_expires_at',
        // Client & Approval fields
        'client_id',
        'approval_status',
        'approved_by',
        'approved_at',
        'rejection_reason',
        'created_by_client_admin',
    ];

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

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
        'last_active_at' => 'datetime',
        'token_expires_at' => 'datetime',
        'approved_at' => 'datetime',
        'force_logout' => 'boolean',
        'is_active' => 'boolean',
        'sms_service_enabled' => 'boolean',
        'promotions_enabled' => 'boolean',
    ];

    // ============ RELATIONSHIPS ============

    /**
     * Get the client this user belongs to.
     */
    public function client()
    {
        return $this->belongsTo(Client::class);
    }

    /**
     * Get the client admin who created this user.
     */
    public function createdByClientAdmin()
    {
        return $this->belongsTo(ClientAdmin::class, 'created_by_client_admin');
    }

    /**
     * Get the admin who approved this user.
     */
    public function approvedBy()
    {
        return $this->belongsTo(Admin::class, 'approved_by');
    }

    /**
     * Get the call logs for the user.
     */
    public function callLogs()
    {
        return $this->hasMany(CallLog::class);
    }

    /**
     * Get the SMS logs for the user.
     */
    public function smsLogs()
    {
        return $this->hasMany(SmsLog::class);
    }

    /**
     * Get the promotion logs for the user.
     */
    public function promotionLogs()
    {
        return $this->hasMany(PromotionLog::class);
    }

    /**
     * Get the session logs for the user.
     */
    public function sessionLogs()
    {
        return $this->hasMany(SessionLog::class);
    }

    /**
     * Get the message templates for the user.
     */
    public function messageTemplates()
    {
        return $this->hasMany(MessageTemplate::class);
    }

    /**
     * Get the user settings.
     */
    public function settings()
    {
        return $this->hasOne(UserSetting::class);
    }

    /**
     * Get or create user settings.
     */
    public function getOrCreateSettings()
    {
        $defaults = [
            'cooldown_hours' => 24,
            'exclude_contacts' => false,
            'sync_enabled' => true,
            'reply_to_incoming' => true,
            'reply_to_missed' => true,
            'reply_to_outgoing' => false,
            'whatsapp_enabled' => false,
        ];

        if (Schema::hasColumn('user_settings', 'user_sms_service_enabled')) {
            $defaults['user_sms_service_enabled'] = true;
        }

        if (Schema::hasColumn('user_settings', 'user_whatsapp_service_enabled')) {
            $defaults['user_whatsapp_service_enabled'] = true;
        }

        return $this->settings ?? $this->settings()->create($defaults);
    }

    /**
     * Get the admin who created this user.
     */
    public function createdBy()
    {
        return $this->belongsTo(Admin::class, 'created_by_admin');
    }

    /**
     * Get the admin who manages this user.
     */
    public function managedBy()
    {
        return $this->belongsTo(Admin::class, 'managed_by_admin');
    }

    /**
     * Check if the user's session is valid for the given device.
     */
    public function isSessionValid(string $deviceId, string $token): bool
    {
        // Check if user is active
        if (!$this->is_active) {
            return false;
        }

        // Check for force logout flag
        if ($this->force_logout) {
            return false;
        }

        // Check device ID matches
        if ($this->session_device_id !== $deviceId) {
            return false;
        }

        // Check token matches
        if ($this->session_token !== hash('sha256', $token)) {
            return false;
        }

        // Check token expiration
        if ($this->token_expires_at && $this->token_expires_at->isPast()) {
            return false;
        }

        return true;
    }

    /**
     * Force logout the user from all devices.
     * Invalidates all active sessions in user_sessions table.
     *
     * @param string $reason  One of: admin_force_logout, password_reset, account_deactivated
     */
    public function forceLogout(string $reason = 'admin_force_logout'): void
    {
        // Invalidate ALL active sessions in user_sessions table
        UserSession::invalidateAll($this->id);

        $this->update([
            'force_logout' => true,
            'force_logout_reason' => $reason,
            'session_token' => null,
            'session_device_id' => null,
        ]);
    }

    /**
     * Clear force logout flag after user logs in again.
     */
    public function clearForceLogout(): void
    {
        $this->update([
            'force_logout' => false,
            'force_logout_reason' => null,
        ]);
    }

    /**
     * Update last active timestamp.
     */
    public function touchLastActive(): void
    {
        $this->update(['last_active_at' => now()]);
    }

    /**
     * Get active template for a specific call type.
     */
    public function getActiveTemplate(string $callType = 'all', string $templateType = 'auto_reply')
    {
        return $this->messageTemplates()
            ->where('is_active', true)
            ->where('type', $templateType)
            ->where(function ($query) use ($callType) {
                $query->where('call_type', $callType)
                    ->orWhere('call_type', 'all');
            })
            ->orderBy('priority')
            ->orderByRaw("CASE WHEN call_type = '{$callType}' THEN 0 ELSE 1 END")
            ->first();
    }

    /**
     * Scope: Active users only.
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope: Users with SMS service enabled.
     */
    public function scopeSmsEnabled($query)
    {
        return $query->where('sms_service_enabled', true);
    }

    /**
     * Scope: Approved users only.
     */
    public function scopeApproved($query)
    {
        return $query->where('approval_status', self::APPROVAL_APPROVED);
    }

    /**
     * Scope: Pending users only.
     */
    public function scopePending($query)
    {
        return $query->where('approval_status', self::APPROVAL_PENDING);
    }

    /**
     * Scope: Rejected users only.
     */
    public function scopeRejected($query)
    {
        return $query->where('approval_status', self::APPROVAL_REJECTED);
    }

    /**
     * Scope: Users for a specific client.
     */
    public function scopeForClient($query, $clientId)
    {
        return $query->where('client_id', $clientId);
    }

    // ============ APPROVAL METHODS ============

    /**
     * Check if user is pending approval.
     */
    public function isPending(): bool
    {
        return $this->approval_status === self::APPROVAL_PENDING;
    }

    /**
     * Check if user is approved.
     */
    public function isApproved(): bool
    {
        return $this->approval_status === self::APPROVAL_APPROVED;
    }

    /**
     * Check if user is rejected.
     */
    public function isRejected(): bool
    {
        return $this->approval_status === self::APPROVAL_REJECTED;
    }

    /**
     * Approve the user (called by SuperAdmin).
     */
    public function approve(Admin $approvedBy): void
    {
        $this->update([
            'approval_status' => self::APPROVAL_APPROVED,
            'approved_by' => $approvedBy->id,
            'approved_at' => now(),
            'rejection_reason' => null,
        ]);
    }

    /**
     * Reject the user (called by SuperAdmin).
     */
    public function reject(Admin $rejectedBy, ?string $reason = null): void
    {
        $this->update([
            'approval_status' => self::APPROVAL_REJECTED,
            'approved_by' => $rejectedBy->id,
            'approved_at' => now(),
            'rejection_reason' => $reason,
        ]);
    }

    /**
     * Check if user can login (approved + active + client has active subscription).
     */
    public function canLogin(): bool
    {
        // Must be approved
        if (!$this->isApproved()) {
            return false;
        }

        // Must be active
        if (!$this->is_active) {
            return false;
        }

        // Client must have active subscription (if user belongs to a client)
        if ($this->client_id && $this->client) {
            if (!$this->client->hasActiveSubscription()) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get login denial reason.
     */
    public function getLoginDenialReason(): ?string
    {
        if ($this->isPending()) {
            return 'Your account is pending approval. Please wait for administrator approval.';
        }

        if ($this->isRejected()) {
            return 'Your account has been rejected. Please contact your administrator.';
        }

        if (!$this->is_active) {
            return 'Your account has been disabled. Please contact your administrator.';
        }

        if ($this->client_id && $this->client) {
            if (!$this->client->is_active) {
                return 'Your organization has been disabled. Please contact support.';
            }

            if (!$this->client->hasActiveSubscription()) {
                return 'Your organization\'s subscription has expired. Please contact your administrator.';
            }
        }

        return null;
    }

    /**
     * Get approval status badge color.
     */
    public function getApprovalBadgeColor(): string
    {
        return match ($this->approval_status) {
            self::APPROVAL_APPROVED => 'success',
            self::APPROVAL_REJECTED => 'danger',
            default => 'warning',
        };
    }

    /**
     * Get user statistics with proper SMS/WhatsApp split.
     */
    public function getStats(): array
    {
        return [
            'total_calls' => $this->callLogs()->count(),
            'total_sms' => $this->smsLogs()->where('channel', 'sms')->count(),
            'total_whatsapp' => $this->smsLogs()->where('channel', 'whatsapp')->count(),
            'total_messages' => $this->smsLogs()->count(),
            'total_promotions' => $this->promotionLogs()->count(),
            'total_whatsapp_promotions' => 0, // promotion_logs table has no channel column
            'calls_by_type' => [
                'incoming' => $this->callLogs()->where('call_type', 'incoming')->count(),
                'outgoing' => $this->callLogs()->where('call_type', 'outgoing')->count(),
                'missed' => $this->callLogs()->where('call_type', 'missed')->count(),
            ],
            'sms_by_status' => [
                'sent' => $this->smsLogs()->where('status', 'sent')->count(),
                'failed' => $this->smsLogs()->where('status', 'failed')->count(),
                'pending' => $this->smsLogs()->where('status', 'pending')->count(),
            ],
            'sms_by_channel' => [
                'sms_sent' => $this->smsLogs()->where('channel', 'sms')->where('status', 'sent')->count(),
                'sms_failed' => $this->smsLogs()->where('channel', 'sms')->where('status', 'failed')->count(),
                'whatsapp_sent' => $this->smsLogs()->where('channel', 'whatsapp')->where('status', 'sent')->count(),
                'whatsapp_failed' => $this->smsLogs()->where('channel', 'whatsapp')->where('status', 'failed')->count(),
            ],
        ];
    }
}
