<?php
/**
 * ============================================================================
 * classes/User.php - Enhanced with Location Hierarchy and Approval System
 * User management class
 * ============================================================================
 */

class User {
    private $db;
    private $table = 'users';
    
    public $id;
    public $phone_number;
    public $password_hash;
    public $full_name;
    public $email;
    public $region_id;
    public $district_id;
    public $subcounty_id;
    public $parish_id;
    public $village_id;
    public $language_preference;
    public $profile_picture;
    public $user_type;
    public $is_verified;
    public $is_active;
    public $approval_status;
    
    public function __construct($db) {
        $this->db = $db;
    }
    
    /**
     * Register new user with location hierarchy and approval workflow
     */
    public function register($data) {
        try {
            // Validate phone number
            $phone = validatePhone($data['phone_number']);
            if (!$phone) {
                return ['success' => false, 'message' => 'Invalid phone number format'];
            }
            
            // Check if phone already exists
            if ($this->phoneExists($phone)) {
                return ['success' => false, 'message' => 'Phone number already registered'];
            }
            
            // Hash password
            $passwordHash = hashPassword($data['password']);
            
            $userType = $data['user_type'] ?? 'farmer';
            
            // Determine approval status based on user type
            // Farmers are auto-approved, buyers and extension officers need approval
            $approvalStatus = ($userType === 'farmer') ? 'approved' : 'pending';
            
            // Insert user
            $sql = "INSERT INTO {$this->table} 
                    (phone_number, password_hash, full_name, email, 
                     region_id, district_id, subcounty_id, parish_id, village_id,
                     language_preference, user_type, approval_status) 
                    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            $stmt = $this->db->prepare($sql);
            $result = $stmt->execute([
                $phone,
                $passwordHash,
                sanitize($data['full_name']),
                sanitize($data['email'] ?? ''),
                $data['region_id'] ?? null,
                $data['district_id'] ?? null,
                $data['subcounty_id'] ?? null,
                $data['parish_id'] ?? null,
                $data['village_id'] ?? null,
                $data['language'] ?? 'en',
                $userType,
                $approvalStatus
            ]);
            
            if ($result) {
                $userId = $this->db->lastInsertId();
                
                // Create buyer profile if buyer
                if ($userType === 'buyer') {
                    $this->createBuyerProfile($userId, $data);
                }
                
                // Create extension officer profile if extension officer
                if ($userType === 'extension_officer') {
                    $this->createExtensionProfile($userId, $data);
                }
                
                // Generate OTP
                $otp = $this->generateOTP($phone);
                
                return [
                    'success' => true, 
                    'message' => 'Registration successful. OTP sent to your phone.',
                    'user_id' => $userId,
                    'otp' => $otp, // Remove in production
                    'requires_approval' => ($approvalStatus === 'pending')
                ];
            }
            
            return ['success' => false, 'message' => 'Registration failed'];
            
        } catch (PDOException $e) {
            error_log("Registration error: " . $e->getMessage());
            return ['success' => false, 'message' => 'Database error occurred'];
        }
    }
    
    /**
     * Create buyer profile
     */
    private function createBuyerProfile($userId, $data) {
        try {
            $sql = "INSERT INTO buyer_profiles 
                    (user_id, buyer_type, business_name, business_registration, tax_id) 
                    VALUES (?, ?, ?, ?, ?)";
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute([
                $userId,
                $data['buyer_type'] ?? 'individual',
                sanitize($data['business_name'] ?? ''),
                sanitize($data['business_registration'] ?? ''),
                sanitize($data['tax_id'] ?? '')
            ]);
            
            return true;
        } catch (PDOException $e) {
            error_log("Buyer profile creation error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Create extension officer profile
     */
    private function createExtensionProfile($userId, $data) {
        try {
            $sql = "INSERT INTO extension_officer_profiles 
                    (user_id, organization, qualification, years_of_experience, specialization) 
                    VALUES (?, ?, ?, ?, ?)";
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute([
                $userId,
                sanitize($data['organization'] ?? ''),
                sanitize($data['qualification'] ?? ''),
                intval($data['experience'] ?? 0),
                sanitize($data['specialization'] ?? '')
            ]);
            
            return true;
        } catch (PDOException $e) {
            error_log("Extension profile creation error: " . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Login user
     */
    public function login($phone, $password) {
        try {
            $phone = validatePhone($phone);
            if (!$phone) {
                return ['success' => false, 'message' => 'Invalid phone number'];
            }
            
            $sql = "SELECT * FROM {$this->table} WHERE phone_number = ? AND is_active = 1";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$phone]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$user) {
                return ['success' => false, 'message' => 'Phone number not found'];
            }
            
            if (!verifyPassword($password, $user['password_hash'])) {
                return ['success' => false, 'message' => 'Incorrect password'];
            }
            
            if (!$user['is_verified']) {
                return [
                    'success' => false, 
                    'message' => 'Account not verified. Please verify your phone number.',
                    'requires_verification' => true,
                    'phone' => $phone
                ];
            }
            
            // Check approval status for buyers and extension officers
            if ($user['approval_status'] === 'pending') {
                return [
                    'success' => false,
                    'message' => 'Your account is pending approval by an administrator. Please wait for approval.',
                    'pending_approval' => true
                ];
            }
            
            if ($user['approval_status'] === 'rejected') {
                return [
                    'success' => false,
                    'message' => 'Your account application was rejected. Please contact support for more information.',
                    'rejected' => true
                ];
            }
            
            // Update last login
            $this->updateLastLogin($user['id']);
            
            // Set session
            setUserSession($user);
            
            // Log activity
            $this->logActivity($user['id'], 'login', 'User logged in successfully');
            
            return [
                'success' => true, 
                'message' => 'Login successful',
                'user' => $user
            ];
            
        } catch (PDOException $e) {
            error_log("Login error: " . $e->getMessage());
            return ['success' => false, 'message' => 'Login failed'];
        }
    }
    
    /**
     * Generate OTP
     */
    private function generateOTP($phone) {
        $otp = generateOTP(6);
        $expiresAt = date('Y-m-d H:i:s', strtotime('+10 minutes'));
        
        $sql = "INSERT INTO otp_verifications (phone_number, otp_code, expires_at) 
                VALUES (?, ?, ?)";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$phone, $otp, $expiresAt]);
        
        return $otp;
    }
    
    /**
     * Verify OTP
     */
    public function verifyOTP($phone, $otp) {
        try {
            $phone = validatePhone($phone);
            
            $sql = "SELECT * FROM otp_verifications 
                    WHERE phone_number = ? AND otp_code = ? 
                    AND is_verified = 0 AND expires_at > NOW() 
                    ORDER BY created_at DESC LIMIT 1";
            
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$phone, $otp]);
            $otpRecord = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if (!$otpRecord) {
                return ['success' => false, 'message' => 'Invalid or expired OTP'];
            }
            
            // Mark OTP as verified
            $sql = "UPDATE otp_verifications SET is_verified = 1 WHERE id = ?";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$otpRecord['id']]);
            
            // Mark user as verified
            $sql = "UPDATE {$this->table} SET is_verified = 1 WHERE phone_number = ?";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$phone]);
            
            // Auto login after verification
            $sql = "SELECT * FROM {$this->table} WHERE phone_number = ?";
            $stmt = $this->db->prepare($sql);
            $stmt->execute([$phone]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);
            
            if ($user) {
                // Check if approval is needed
                if ($user['approval_status'] === 'pending') {
                    return [
                        'success' => true,
                        'message' => 'Phone number verified. Your account is pending admin approval.',
                        'pending_approval' => true
                    ];
                }
                
                setUserSession($user);
            }
            
            return [
                'success' => true, 
                'message' => 'Phone number verified successfully'
            ];
            
        } catch (PDOException $e) {
            error_log("OTP verification error: " . $e->getMessage());
            return ['success' => false, 'message' => 'Verification failed'];
        }
    }
    
    /**
     * Resend OTP
     */
    public function resendOTP($phone) {
        $phone = validatePhone($phone);
        if (!$phone) {
            return ['success' => false, 'message' => 'Invalid phone number'];
        }
        
        $otp = $this->generateOTP($phone);
        
        return [
            'success' => true, 
            'message' => 'OTP resent successfully',
            'otp' => $otp // Remove in production
        ];
    }
    
    /**
     * Check if phone exists
     */
    private function phoneExists($phone) {
        $sql = "SELECT id FROM {$this->table} WHERE phone_number = ?";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$phone]);
        return $stmt->fetch() !== false;
    }
    
    /**
     * Get user by ID
     */
    public function getUserById($id) {
        $sql = "SELECT * FROM {$this->table} WHERE id = ?";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Get user with full location details
     */
    public function getUserWithLocation($id) {
        $sql = "SELECT 
                    u.*,
                    r.region_name,
                    d.district_name,
                    s.subcounty_name,
                    p.parish_name,
                    v.village_name
                FROM {$this->table} u
                LEFT JOIN regions r ON u.region_id = r.id
                LEFT JOIN districts d ON u.district_id = d.id
                LEFT JOIN subcounties s ON u.subcounty_id = s.id
                LEFT JOIN parishes p ON u.parish_id = p.id
                LEFT JOIN villages v ON u.village_id = v.id
                WHERE u.id = ?";
        
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    
    /**
     * Update user profile
     */
    public function updateProfile($userId, $data) {
        try {
            $sql = "UPDATE {$this->table} SET 
                    full_name = ?,
                    email = ?,
                    region_id = ?,
                    district_id = ?,
                    subcounty_id = ?,
                    parish_id = ?,
                    village_id = ?,
                    language_preference = ?,
                    updated_at = CURRENT_TIMESTAMP
                    WHERE id = ?";
            
            $stmt = $this->db->prepare($sql);
            $result = $stmt->execute([
                sanitize($data['full_name']),
                sanitize($data['email'] ?? ''),
                $data['region_id'] ?? null,
                $data['district_id'] ?? null,
                $data['subcounty_id'] ?? null,
                $data['parish_id'] ?? null,
                $data['village_id'] ?? null,
                $data['language_preference'] ?? 'en',
                $userId
            ]);
            
            if ($result) {
                return ['success' => true, 'message' => 'Profile updated successfully'];
            }
            
            return ['success' => false, 'message' => 'Update failed'];
            
        } catch (PDOException $e) {
            error_log("Profile update error: " . $e->getMessage());
            return ['success' => false, 'message' => 'Update failed'];
        }
    }
    
    /**
     * Update last login
     */
    private function updateLastLogin($userId) {
        $sql = "UPDATE {$this->table} SET last_login = CURRENT_TIMESTAMP WHERE id = ?";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([$userId]);
    }
    
    /**
     * Log user activity
     */
    public function logActivity($userId, $action, $description = '') {
        $sql = "INSERT INTO activity_log (user_id, action, description, ip_address, user_agent) 
                VALUES (?, ?, ?, ?, ?)";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([
            $userId,
            $action,
            $description,
            $_SERVER['REMOTE_ADDR'] ?? '',
            $_SERVER['HTTP_USER_AGENT'] ?? ''
        ]);
    }
}
?>