<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

require APPPATH . '/libraries/BaseController.php';

use Google\Cloud\Firestore\FirestoreClient;

class Customer extends BaseController
{
    private const POSTS_PER_PAGE = 9;

    public function __construct()
    {
        parent::__construct();
        $this->load->model('customer_model');
        $this->load->helper(['url', 'form']);
        $this->load->library('form_validation');
    }

    /**
     * Fetch users from Firestore with optional status filter.
     */
    private function fetchUsersByStatus(?string $status = null): array
    {
        if ($status !== null && $status !== '') {
            $rawUsers = $this->common->readdatafromcollectionwhereclause('Users', 'status', '==', $status);
        } else {
            $rawUsers = $this->common->readdatafromcollectionwhereclause('Users');
        }

        $rawUsers = is_array($rawUsers) ? $rawUsers : [];
        $users = [];

        foreach ($rawUsers as $userId => $userData) {
            if (!is_array($userData)) {
                continue;
            }

            $isDeleted = isset($userData['isDeleted']) ? (bool)$userData['isDeleted'] : false;
            if ($isDeleted) {
                continue;
            }

            $userData['id'] = $userId;

            if (empty($userData['fullName']) && !empty($userData['name'])) {
                $userData['fullName'] = $userData['name'];
            }

            $users[$userId] = $userData;
        }

        uasort($users, static function ($a, $b) {
            $nameA = strtolower($a['fullName'] ?? $a['userName'] ?? '');
            $nameB = strtolower($b['fullName'] ?? $b['userName'] ?? '');
            return $nameA <=> $nameB;
        });

        return $users;
    }

    /**
     * Apply a case-insensitive search filter to a user list.
     */
    private function filterUsersBySearch(array $users, string $searchText): array
    {
        $searchText = trim($searchText);
        if ($searchText === '') {
            return $users;
        }

        $searchNeedle = strtolower($searchText);
        $filtered = [];

        foreach ($users as $userId => $userData) {
            $haystackParts = [];

            foreach (['fullName', 'email', 'userName', 'phoneNumber'] as $key) {
                if (!empty($userData[$key])) {
                    $haystackParts[] = strtolower((string)$userData[$key]);
                }
            }

            $haystack = implode(' ', $haystackParts);
            if ($haystack === '') {
                continue;
            }

            if (strpos($haystack, $searchNeedle) !== false) {
                $filtered[$userId] = $userData;
            }
        }

        return $filtered;
    }

    public function index()
    {
        $this->customers();
    }

    /**
     * Display all customers
     */
    public function customers()
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            $searchText = '';
            if (!empty($this->input->post('searchText'))) {
                $searchText = $this->security->xss_clean($this->input->post('searchText'));
            }
            $data['searchText'] = $searchText;

            $allUsers = $this->fetchUsersByStatus();
            $data['customers'] = $this->filterUsersBySearch($allUsers, $searchText);

            $this->global['pageTitle'] = 'StreamAdmin : Customers';
            $this->loadViews("customers/customers", $this->global, $data, NULL);
        }
    }

    /**
     * Display active customers
     */
    public function active()
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            $searchText = '';
            if (!empty($this->input->post('searchText'))) {
                $searchText = $this->security->xss_clean($this->input->post('searchText'));
            }
            $data['searchText'] = $searchText;

            $activeUsers = $this->fetchUsersByStatus('active');
            $data['customers'] = $this->filterUsersBySearch($activeUsers, $searchText);

            $this->global['pageTitle'] = 'StreamAdmin : Active Customers';
            $this->loadViews("customers/active", $this->global, $data, NULL);
        }
    }

    /**
     * Display warned customers
     */
    public function warned()
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            $searchText = '';
            if (!empty($this->input->post('searchText'))) {
                $searchText = $this->security->xss_clean($this->input->post('searchText'));
            }
            $data['searchText'] = $searchText;

            $warnedUsers = $this->fetchUsersByStatus('warning');
            $data['customers'] = $this->filterUsersBySearch($warnedUsers, $searchText);

            $this->global['pageTitle'] = 'StreamAdmin : Warned Customers';
            $this->loadViews("customers/warned", $this->global, $data, NULL);
        }
    }

    /**
     * Display suspended customers
     */
    public function suspended()
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            $searchText = '';
            if (!empty($this->input->post('searchText'))) {
                $searchText = $this->security->xss_clean($this->input->post('searchText'));
            }
            $data['searchText'] = $searchText;

            $suspendedUsers = $this->fetchUsersByStatus('suspend');
            $data['customers'] = $this->filterUsersBySearch($suspendedUsers, $searchText);

            $this->global['pageTitle'] = 'StreamAdmin : Suspended Customers';
            $this->loadViews("customers/suspended", $this->global, $data, NULL);
        }
    }

    /**
     * Display add customer form
     */
    public function addCustomer()
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            $this->global['pageTitle'] = 'StreamAdmin : Add New Customer';
            $this->loadViews("customers/addCustomer", $this->global, NULL, NULL);
        }
    }

    /**
     * Add new customer
     */
    public function addNewCustomer()
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            $this->load->library('form_validation');

            $this->form_validation->set_rules('fullName', 'Full Name', 'trim|required|max_length[128]');
            $this->form_validation->set_rules('userName', 'Username', 'trim|required|max_length[50]');
            $this->form_validation->set_rules('email', 'Email', 'trim|required|valid_email|max_length[128]');
            $this->form_validation->set_rules('phoneNumber', 'Phone Number', 'trim|max_length[20]');
            $this->form_validation->set_rules('dob', 'Date of Birth', 'trim');
            $this->form_validation->set_rules('password', 'Password', 'required|min_length[6]|max_length[20]');

            if ($this->form_validation->run() == FALSE) {
                $this->addCustomer();
            } else {
                $fullName = ucwords(strtolower($this->security->xss_clean($this->input->post('fullName'))));
                $userName = strtolower($this->security->xss_clean($this->input->post('userName')));
                $email = strtolower($this->security->xss_clean($this->input->post('email')));
                $phoneNumber = $this->security->xss_clean($this->input->post('phoneNumber'));
                $dob = $this->security->xss_clean($this->input->post('dob'));
                $password = $this->input->post('password');
                $blueTick = $this->input->post('blueTick');

                $currentTime = time() * 1000;
                
                $customerInfo = array(
                    'fullName' => $fullName,
                    'userName' => $userName,
                    'email' => $email,
                    'status' => 'active',
                    'password' => $password,
                    'userRole' => 'user',
                    'IsActive' => true,
                    'NooFwarning' => 0,
                    'joinDate' => $currentTime,
                    'lastActiveDate' => $currentTime,
                    'loginMethod' => 'Email',
                    'platform' =>  'Web',
                    'userCoins' => 0,
                    'userFollowers' => array(),
                    'userFollowings' => array(),
                    'token' => ''
                );


                if (!empty($phoneNumber)) {
                    $customerInfo['phoneNumber'] = $phoneNumber;
                }

                if (!empty($dob)) {
                    $customerInfo['dob'] = strtotime($dob)*1000;
                }
                if (!empty($blueTick)) {
                if($blueTick == 'yes') {
                    $customerInfo['hasBlueCheck'] = true;
                    $customerInfo['tickRequestStatus'] = "approved";
                }
               
                }
                $result = $this->customer_model->add_customer($customerInfo);
                if ($result) {
                    $this->session->set_flashdata('success', 'New Customer created successfully');
                } else {
                    $this->session->set_flashdata('error', 'Customer creation failed');
                }

                redirect('customer/addCustomer');
            }
        }
    }

    /**
     * View customer details
     */
    public function viewCustomer($customerId = NULL)
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            if ($customerId == null) {
                redirect('customer/customers');
            }

            $data['customerInfo'] = $this->customer_model->get_customerdetails($customerId);
            $data['customerId'] = $customerId;

            $postsPage = $this->common->readdatafromcollectionWithPagination(
                'Posts',
                'createdDate',
                'DESC',
                1,
                self::POSTS_PER_PAGE,
                [
                    [
                        'field'    => 'userId',
                        'operator' => '==',
                        'value'    => $customerId,
                    ],
                    [
                        'field'    => 'isArchived',
                        'operator' => '==',
                        'value'    => false,
                    ],
                ]
            );

            $rawPosts = [];
            foreach ($postsPage['items'] as $item) {
                if (!isset($item['id'])) {
                    continue;
                }
                $rawPosts[$item['id']] = $item;
            }

            $data['customerPosts'] = $this->preparePosts($rawPosts);
            $data['postsPagination'] = [
                'current' => $postsPage['page'],
                'perPage' => $postsPage['perPage'],
                'hasMore' => $postsPage['hasMore'],
            ];

            $this->global['pageTitle'] = 'StreamAdmin : Customer Details';
            $this->loadViews("customers/viewCustomer", $this->global, $data, NULL);
        }
    }

    public function loadCustomerPosts()
    {
        if (!$this->isAdmin() || !$this->input->is_ajax_request()) {
            show_404();
            return;
        }

        $customerId = trim($this->input->get('customerId'));
        if (empty($customerId)) {
            $this->output
                ->set_content_type('application/json')
                ->set_output(json_encode(['success' => false, 'message' => 'Invalid customer id']));
            return;
        }

        $page = (int)$this->input->get('page');
        $page = $page > 1 ? $page : 2;

        $postsPage = $this->common->readdatafromcollectionWithPagination(
            'Posts',
            'createdDate',
            'DESC',
            $page,
            self::POSTS_PER_PAGE,
            [
                [
                    'field'    => 'userId',
                    'operator' => '==',
                    'value'    => $customerId,
                ],
                [
                    'field'    => 'isArchived',
                    'operator' => '==',
                    'value'    => false,
                ]
            ]
        );

        $rawPosts = [];
        foreach ($postsPage['items'] as $item) {
            if (!isset($item['id'])) {
                continue;
            }
            $rawPosts[$item['id']] = $item;
        }

        $posts = $this->preparePosts($rawPosts);
        $html = $this->load->view('foryou/_posts', ['posts' => $posts, 'context' => 'customer'], true);

        $response = [
            'success' => true,
            'html'    => $html,
            'page'    => $postsPage['page'],
            'hasMore' => $postsPage['hasMore'],
        ];

        $this->output
            ->set_content_type('application/json')
            ->set_output(json_encode($response));
    }

    private function preparePosts(array $rawPosts): array
    {
        if (empty($rawPosts)) {
            return [];
        }

        $posts = [];
        $userCache = [];

        foreach ($rawPosts as $postId => $post) {
            $post['id'] = $postId;
            $post['createdDate'] = isset($post['createdDate']) ? (int)$post['createdDate'] : 0;
            $posts[] = $post;
        }

        usort($posts, function ($a, $b) {
            return ($b['createdDate'] ?? 0) <=> ($a['createdDate'] ?? 0);
        });

        foreach ($posts as &$post) {
            $userId = $post['userId'] ?? '';
            $userSnapshot = null;

            if (!empty($userId)) {
                if (array_key_exists($userId, $userCache)) {
                    $userSnapshot = $userCache[$userId];
                } else {
                    $userSnapshot = $this->customer_model->get_customerdetails($userId);
                    $userCache[$userId] = $userSnapshot;
                }
            }

            $post['author'] = [
                'name'     => $userSnapshot['fullName'] ?? ($userSnapshot['userName'] ?? 'Unknown User'),
                'userName' => $userSnapshot['userName'] ?? '',
                'avatar'   => $userSnapshot['image'] ?? '',
            ];

            $post['address'] = $post['address'] ?? '';
            $post['city'] = $post['city'] ?? '';
            $post['privacy'] = $post['privacy'] ?? 'Public';
            $post['allowComments'] = isset($post['allowComments']) ? (bool)$post['allowComments'] : true;
            $post['isPin'] = isset($post['isPin']) ? (bool)$post['isPin'] : false;
            $post['isDraft'] = isset($post['isDraft']) ? (bool)$post['isDraft'] : false;
            $post['hashtags'] = isset($post['hashtags']) && is_array($post['hashtags']) ? $post['hashtags'] : [];
            $post['details'] = $post['detials'] ?? ($post['details'] ?? '');
            $post['songDetails'] = $post['songDetails'] ?? '';
            $post['totalViews'] = 0;

            if (!empty($post['totalviews']) && is_array($post['totalviews'])) {
                $post['totalViews'] = array_reduce($post['totalviews'], function ($carry, $value) {
                    return $carry + (int)$value;
                }, 0);
            }
        }

        return $posts;
    }

    /**
     * Edit customer form
     */
    public function editCustomer($customerId = NULL)
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            if ($customerId == null) {
                redirect('customer/customers');
            }

            $data['customerInfo'] = $this->customer_model->get_customerdetails($customerId);
            $data['customerId'] = $customerId;

            $this->global['pageTitle'] = 'StreamAdmin : Edit Customer';
            $this->loadViews("customers/editCustomer", $this->global, $data, NULL);
        }
    }

    /**
     * Update customer
     */
    public function updateCustomer()
    {
        if (!$this->isAdmin()) {
            $this->loadThis();
        } else {
            $this->load->library('form_validation');

            $customerId = $this->input->post('customerId');
            $email = $this->input->post('email');

            $this->form_validation->set_rules('fullName', 'Full Name', 'trim|required|max_length[128]');
            $this->form_validation->set_rules('userName', 'Username', 'trim|required|max_length[50]');

            if ($this->form_validation->run() == FALSE) {
                $this->editCustomer($customerId);
            } else {
                $fullName = ucwords(strtolower($this->security->xss_clean($this->input->post('fullName'))));
                $userName = strtolower($this->security->xss_clean($this->input->post('userName')));
                $isActive = $this->input->post('IsActive') === 'true' ? true : false;
                $userCoins = intval($this->security->xss_clean($this->input->post('userCoins')));

                $customerData = array(
                    'old' => array('email' => $email),
                    'new' => array(
                        'fullName' => $fullName,
                        'userName' => $userName,
                        'IsActive' => $isActive,
                        'userCoins' => $userCoins,
                        'lastActiveDate' => time() * 1000
                    )
                );

                $result = $this->customer_model->update_customer($customerData);

                if ($result) {
                    $this->session->set_flashdata('success', 'Customer updated successfully');
                } else {
                    $this->session->set_flashdata('error', 'Customer update failed');
                }

                redirect('customer/customers');
            }
        }
    }

    /**
     * Update customer password
     */
    public function updatePassword()
    {
        if (!$this->isAdmin()) {
            echo (json_encode(array('status' => 'access')));
        } else {
            $customerId = $this->input->post('customerId');
            $newPassword = $this->input->post('newPassword');

            if (empty($customerId) || empty($newPassword)) {
                echo (json_encode(array('status' => FALSE, 'message' => 'Invalid data')));
                return;
            }

            $result = $this->customer_model->update_customerpassword($customerId, $newPassword);

            if ($result) {
                echo (json_encode(array('status' => TRUE, 'message' => 'Password updated successfully')));
            } else {
                echo (json_encode(array('status' => FALSE, 'message' => 'Password update failed')));
            }
        }
    }

    /**
     * Toggle customer status (enable/disable)
     */
    public function toggleStatus()
    {
        if (!$this->isAdmin()) {
            echo (json_encode(array('status' => 'access')));
        } else {
            $customerId = $this->input->post('customerId');
            $currentStatus = $this->input->post('currentStatus');

            if (empty($customerId)) {
                echo (json_encode(array('status' => FALSE)));
                return;
            }

            $this->load->model('common');
            $result = $this->common->update_customerstatus($customerId, $currentStatus);

            if ($result) {
                echo (json_encode(array('status' => TRUE)));
            } else {
                echo (json_encode(array('status' => FALSE)));
            }
        }
    }

    /**
     * Add warning to customer
     */
    public function addWarning()
    {
        if (!$this->isAdmin()) {
            echo (json_encode(array('status' => 'access')));
        } else {
            $customerId = $this->input->post('customerId');
            $email = $this->input->post('email');
            $currentWarnings = intval($this->input->post('currentWarnings'));

            if (empty($customerId) || empty($email)) {
                echo (json_encode(array('status' => FALSE)));
                return;
            }

            $customerData = array(
                'old' => array('email' => $email),
                'new' => array(
                    'NooFwarning' => $currentWarnings + 1
                )
            );

            $result = $this->customer_model->update_customer($customerData);

            if ($result) {
                echo (json_encode(array('status' => TRUE)));
            } else {
                echo (json_encode(array('status' => FALSE)));
            }
        }
    }

    /**
     * Suspend/Activate customer
     */
    public function toggleSuspend()
    {
        if (!$this->isAdmin()) {
            echo json_encode(['status' => 'access']);
            return;
        }

        $customerId    = trim($this->input->post('customerId'));
        $email         = trim($this->input->post('email'));
        $postedStatus  = strtolower(trim((string)$this->input->post('status')));

        if ($customerId === '' || $email === '') {
            echo json_encode(['status' => false, 'message' => 'Invalid data']);
            return;
        }

        $this->load->model('common');

        $userSnapshot = $this->common->readdatadocument('Users', $customerId);
        if (!is_array($userSnapshot)) {
            echo json_encode(['status' => false, 'message' => 'User not found']);
            return;
        }

        $currentStatus = strtolower($userSnapshot['status'] ?? ($postedStatus !== '' ? $postedStatus : 'active'));

        if ($currentStatus === 'active' || $currentStatus === 'warning') {
            $result = $this->suspendCustomerAccount($customerId, 'Manual suspension via customer directory');
        } else {
            $result = $this->reactivateCustomerAccount($customerId, 'Manual reactivation via customer directory');
        }

        if (!$result['success']) {
            echo json_encode(['status' => false, 'message' => $result['message']]);
            return;
        }

        echo json_encode([
            'status'    => true,
            'message'   => $result['message'],
            'newStatus' => $result['newStatus'],
        ]);
    }

    private function suspendCustomerAccount(string $userId, string $reason): array
    {
        try {
            $firebase = $this->firebase->init();
            $auth = $firebase->createAuth();
            $auth->disableUser($userId);
        } catch (\Throwable $e) {
            log_message('error', 'Failed to disable user ' . $userId . ': ' . $e->getMessage());
            return ['success' => false, 'message' => 'Unable to disable user in Firebase Auth'];
        }

        $nowMs = time() * 1000;
        $updatePayload = [
            'status'          => 'suspend',
            'approved'        => false,
            'IsActive'        => false,
            'lastSuspendedAt' => $nowMs,
        ];

        $firestoreUpdated = $this->common->updatedatamodel('Users', $userId, $updatePayload);
        if (!$firestoreUpdated) {
            return ['success' => false, 'message' => 'Failed to update user status'];
        }

        $this->recordSuspensionHistoryEntry($userId, $reason, null, true, 'suspend');

        return [
            'success'   => true,
            'message'   => 'User suspended successfully',
            'newStatus' => 'suspend',
        ];
    }

    private function reactivateCustomerAccount(string $userId, string $reason): array
    {
        try {
            $firebase = $this->firebase->init();
            $auth = $firebase->createAuth();
            $auth->enableUser($userId);
        } catch (\Throwable $e) {
            log_message('error', 'Failed to enable user ' . $userId . ': ' . $e->getMessage());
            return ['success' => false, 'message' => 'Unable to enable user in Firebase Auth'];
        }

        $nowMs = time() * 1000;
        $updatePayload = [
            'status'           => 'active',
            'approved'         => true,
            'IsActive'         => true,
            'warningCount'     => 0,
            'lastReactivated'  => $nowMs,
        ];

        $firestoreUpdated = $this->common->updatedatamodel('Users', $userId, $updatePayload);
        if (!$firestoreUpdated) {
            return ['success' => false, 'message' => 'Failed to update user status'];
        }

        $this->recordSuspensionHistoryEntry($userId, $reason, null, false, 'reactivate');

        return [
            'success'   => true,
            'message'   => 'User activated successfully',
            'newStatus' => 'active',
        ];
    }

    private function recordSuspensionHistoryEntry(string $userId, string $reason, ?int $durationHours, bool $isPermanent, string $action): void
    {
        $historyId = $action . '_' . time() . '_' . substr($userId, -6);
        $historyData = [
            'id'            => $historyId,
            'userId'        => $userId,
            'reason'        => $reason,
            'durationHours' => $durationHours,
            'handledBy'     => $this->currentAdminId(),
            'createdAt'     => time() * 1000,
            'isPermanent'   => $isPermanent,
            'action'        => $action,
        ];

        $this->common->adddatamodel('SuspensionHistory', $historyId, $historyData);
    }

    private function currentAdminId(): string
    {
        $session = $this->session->userdata('session_data');
        return $session['userId'] ?? ($session['id'] ?? '');
    }

    /**
     * Delete customer - Remove from both Firebase Auth and Firestore
     */
    public function deleteCustomer()
    {
        if (!$this->isAdmin()) {
            echo (json_encode(array('status' => 'access')));
        } else {
            $customerId = $this->input->post('customerId');

            if (empty($customerId)) {
                echo (json_encode(array('status' => FALSE, 'message' => 'Customer ID is required')));
                return;
            }

            // First get customer details to backup before deletion
            $customerInfo = $this->customer_model->get_customerdetails($customerId);
            
            if (empty($customerInfo)) {
                echo (json_encode(array('status' => FALSE, 'message' => 'Customer not found')));
                return;
            }

            // Delete from Firebase Auth first
            $authResult = $this->customer_model->delete_customer($customerId);

            if ($authResult) {
                // Then delete from Firestore Users collection
                $x = $this->config->item('firebase_app_key');
                
                try {
                    $firestore = new FirestoreClient([
                        'projectId' => 'stream-c7e91',
                        'keyFile' => json_decode(file_get_contents($x), true)
                    ]);
                    
                    $docRef = $firestore->collection('Users')->document($customerId);
                    $docRef->delete();
                    
                    echo (json_encode(array('status' => TRUE, 'message' => 'Customer deleted successfully from both Auth and Firestore')));
                } catch (\Exception $e) {
                    // Auth was deleted but Firestore failed - log this
                    echo (json_encode(array('status' => FALSE, 'message' => 'Customer deleted from Auth but Firestore deletion failed: ' . $e->getMessage())));
                }
            } else {
                echo (json_encode(array('status' => FALSE, 'message' => 'Failed to delete customer from Firebase Auth')));
            }
        }
    }
}

