<?php

use WeDevs\PM\Core\Textdomain\Textdomain;
use WeDevs\PM\Core\Notifications\Email;
use League\Fractal;
use League\Fractal\Resource\Item as Item;
use WeDevs\PM\Task\Transformers\Task_Transformer;
use WeDevs\PM\Task\Models\Task;
use WeDevs\PM\Task_List\Models\Task_List;
use WeDevs\PM\Milestone\Models\Milestone;
use WeDevs\PM\Discussion_Board\Models\Discussion_Board;
use Illuminate\Database\Eloquent\Collection;
use WeDevs\PM\Project\Models\Project;

/**
 * Get translated text (Deprecated)
 * 
 * @deprecated This function is deprecated. Use WordPress i18n functions (__(), _e(), etc.) directly instead.
 * 
 * @param string $key The text key
 * @return mixed
 */
function wedevs_pm_get_text( $key ) {
    // This function is kept only for backward compatibility with pm-pro plugin
    // All core functionality now uses proper WordPress i18n functions
    _deprecated_function( __FUNCTION__, '2.6.0', 'WordPress i18n functions (__(), _e(), etc.)' );
    
    // Return empty array for any key to prevent errors
    return array();
}

function wedevs_pm_get_wp_timezone() {
    $current_offset = get_option('gmt_offset');
    $wp_timezone = get_option('timezone_string');

    // Remove old Etc mappings. Fallback to gmt_offset.
    if ( false !== strpos( $wp_timezone, 'Etc/GMT' ) ) {
        $wp_timezone = '';
    }

    // Create a UTC+- zone if no timezone string exists
    if ( empty( $wp_timezone ) ) {
        if ( 0 == $current_offset ) {
            $wp_timezone = 'UTC+0';
        } elseif ($current_offset < 0) {
            $wp_timezone = 'UTC' . $current_offset;
        } else {
            $wp_timezone = 'UTC+' . $current_offset;
        }
    }

    return $wp_timezone;
}

function wedevs_pm_tzcode_to_tzstring( $tzcode ) {
    $timezones = wedevs_pm_config( 'timezones' );
    $timezone = $tzcode;

    if ( array_key_exists( $tzcode , $timezones ) ) {
        $timezone = $timezones[ $tzcode ];
    }

    return $timezone;
}

function wedevs_pm_tzstring_to_tzcode( $tzstr ) {
    $timezones = wedevs_pm_config( 'timezones' );
    $default = '';

    foreach ( $timezones as $tzcode => $tzstring ) {
        if ( $tzstring == $tzstr ) {
            return $tzcode;
        }
    }

    return $default;
}

function wedevs_pm_format_date( $date ) {

        if ( $date && !is_object($date) ) {
            $date =  \Carbon\Carbon::parse($date);
        }
        $date_format = get_option( 'date_format' );
        $time_format = get_option( 'time_format' );
        $timezone    = wedevs_pm_get_wp_timezone();

        return [
            'date'      => $date ? $date->format( 'Y-m-d' ) : null,
            'formatted_date' => $date ? $date->format( $date_format ) : null,
            'time'      => $date ? $date->format( 'H:i:s' ) : null,
            'datetime'      => $date ? $date->format( 'Y-m-d H:i:s' ) : null,
            'timezone'  => wedevs_pm_tzcode_to_tzstring( $timezone ),
            'timestamp' => $date ?  $date->toATOMString() : null
        ];
}

function wedevs_pm_date_format( $date ) {

    $date_format = get_option( 'date_format' );

    return $date ? gmdate( $date_format, strtotime( $date ) ) : '';
}

function wedevs_pm_make_carbon_date( $date ) {
    $timezone = wedevs_pm_get_wp_timezone();
    $timezone = wedevs_pm_tzcode_to_tzstring( $timezone );
    $time = $date ? strtotime( $date ) : null;

    if ( $time ) {
        return new \Carbon\Carbon( $date, $timezone );
    }

    return null;
}

function wedevs_pm_get_wp_roles() {
    // Use wp_roles() function which properly initializes the global without override warnings
    if ( function_exists( 'wp_roles' ) ) {
        return wp_roles()->get_names();
    }

    // Fallback for older WordPress versions (pre-4.3)
    global $wp_roles;

    if ( ! $wp_roles ) {
        // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Initializing global for WordPress < 4.3 compatibility
        $wp_roles = new WP_Roles();
    }

    return $wp_roles->get_names();
}

function wedevs_pm_get_setting( $key = null, $project_id = false ) {
    $settings     = null;
    $all_settings = null;

    if ( $key && $project_id ) {
        $settings = \WeDevs\PM\Settings\Models\Settings::where( 'key', $key )
            ->where('project_id', $project_id)
            ->first();
    } else if ($key) {
        $settings = \WeDevs\PM\Settings\Models\Settings::where( 'key', $key )
            ->first();
    } else {
        $hide = \WeDevs\PM\Settings\Models\Settings::$hideSettings;
        $all_settings = \WeDevs\PM\Settings\Models\Settings::whereNotIn( 'key', $hide )->get();
    }

    if ( $settings ) {
        return $settings->value;
    }

    if ( $all_settings ) {
        $settings =  $all_settings->toArray();
        return wp_list_pluck( $settings, 'value', 'key' );
    }

    return null;
}

function wedevs_pm_get_settings( $key = null, $project_id = false ) {
    $settings = null;

    if ( $key && $project_id ) {
        $settings = \WeDevs\PM\Settings\Models\Settings::where( 'key', $key )
            ->where('project_id', $project_id)
            ->get()
            ->toArray();
    } else if ( $key ) {
        $settings = \WeDevs\PM\Settings\Models\Settings::where( 'key', $key )
            ->get()
            ->toArray();

    } else if ( $project_id ) {
        $settings = \WeDevs\PM\Settings\Models\Settings::where( 'project_id', $project_id )
            ->get()
            ->toArray();
    }

    return $settings;
}

function wedevs_pm_delete_settings( $key, $project_id = false ) {

    if ( $project_id ) {
        $settings = \WeDevs\PM\Settings\Models\Settings::where( 'key', $key )
            ->where('project_id', $project_id)
            ->first();
    } else {
        $settings = \WeDevs\PM\Settings\Models\Settings::where( 'key', $key )
            ->first();
    }

    if ( $settings ) {
        $settings->delete();

        wp_send_json_success();
    }

    wp_send_json_error();
}

function wedevs_pm_set_settings( $key, $value, $project_id = false ){

    if ( $project_id == false ){
        $settings = \WeDevs\PM\Settings\Models\Settings::updateOrCreate(['key' => $key], ['value' => $value ]);
    }else {
        $settings = \WeDevs\PM\Settings\Models\Settings::updateOrCreate(['key' => $key, 'project_id' => $project_id ], ['value' => $value ]);
    }

    return $settings;
}

function wedevs_pm_add_meta( $id, $project_id, $type, $key, $value ) {
    // phpcs:disable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Custom Eloquent model table (pm_meta), not WordPress core meta tables.
    WeDevs\PM\Common\Models\Meta::create([
        'entity_id'   => $id,
        'entity_type' => $type,
        'meta_key'    => $key,
        'meta_value'  => $value,
        'project_id'  => $project_id,
        'created_by'  => get_current_user_id(),
        'created_by'  => get_current_user_id()
    ]);
    // phpcs:enable WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value
}


function wedevs_pm_update_meta( $id, $project_id, $type, $key, $value ) {
    // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Custom Eloquent model table (pm_meta), not WordPress core meta tables.
    $meta = WeDevs\PM\Common\Models\Meta::where( 'entity_id', $id )
        ->where( 'project_id', $project_id )
        ->where( 'entity_type', $type )
        ->where( 'meta_key', $key )
        ->first();

    if ( $meta ) {
        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- Custom Eloquent model table (pm_meta), not WordPress core meta tables.
        $meta->update(['meta_value' => $value]);
    } else {
        wedevs_pm_add_meta( $id, $project_id, $type, $key, $value );
    }
}

function wedevs_pm_get_meta( $entity_id, $project_id, $type, $key, $single = true ) {
    $entity_id = wedevs_pm_get_prepare_data( $entity_id );

    $meta = WeDevs\PM\Common\Models\Meta::where( function($q) use($project_id) {
            if ( !empty( $project_id ) ) {
                $q->where( 'project_id', $project_id );
            }
        } )
        ->whereIn( 'entity_id', $entity_id )
        ->where( 'entity_type',  $type )
        ->where( 'meta_key', $key );

    if ( $single ) {
        $meta = $meta->first();
    } else {
        $meta = $meta->get()->toArray();
    }

    return $meta;
}

function wedevs_pm_delete_meta( $id, $project_id, $type, $key = false ) {
    $meta = WeDevs\PM\Common\Models\Meta::where( 'entity_id', $id )
        ->where( 'project_id', $project_id )
        ->where( 'entity_type', $type );

    if ( $key ) {
        $meta = $meta->where( 'meta_key', $key );
        $meta = $meta->first();
    }

    if ( $meta ) {
        $meta->delete();
    }
}

function wedevs_pm_get_response( $resource, $extra = [] ) {
    $manager = new \League\Fractal\Manager();
    $data_serialize = new \League\Fractal\Serializer\DataArraySerializer();
    $manager->setSerializer( $data_serialize );

    // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified at REST API layer via register_rest_route() in WP_Router.
    if ( isset( $_GET['with'] ) ) {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified at REST API layer via register_rest_route() in WP_Router.
        $manager->parseIncludes( sanitize_text_field( wp_unslash( $_GET['with'] ) ) );
    }

    if ($resource) {
        $response = $manager->createData( $resource )->toArray();

    } else {
        $response = [];
    }

    return array_merge( $extra, $response );
}

/**
 * Print debug output
 */
function wedevs_pm_pr() {
    $args = func_get_args();

    foreach ( $args as $arg ) {
        echo '<pre>'; print_r( $arg ); '</pre>';
    }
}

function wedevs_pm_pro_get_project_capabilities( $project_id ) {
    $caps = WeDevs\PM\Settings\Models\Settings::where('key', 'capabilities')
        ->where('project_id', $project_id)
        ->first();

    if ( ! $caps ) {
        return [
            'co_worker' => wedevs_pm_default_co_caps(),
            'client'    => wedevs_pm_default_client_caps()
        ];
    }

    $formatedCaps = [];

    foreach ( $caps->value as $key => $value ) {
        $formatedCaps[$key] = array_map( function($val) {
            return $val === 'true' ? true : false;
        }, $value );
    }

    return $formatedCaps;
}

function wedevs_pm_is_user_in_project( $project_id, $user_id = false ) {
    $user_id = $user_id ? $user_id : get_current_user_id();

    $user_in_project = WeDevs\PM\User\Models\User_Role::where( 'project_id', $project_id )
        ->where( 'user_id', $user_id )
        ->first();

    return $user_in_project ? true : false;
}

function wedevs_pm_is_user_in_task( $project_id, $user_id = false ) {
    $user_id = $user_id ? $user_id : get_current_user_id();

    $user_in_task = WeDevs\PM\Common\Models\Assignee::where( 'project_id', $project_id )
        ->where( 'assigned_to', $user_id )
        ->first();

    return $user_in_task ? true : false;
}

function wedevs_pm_get_role( $project_id, $user_id = false ) {
    $user_id = $user_id ? $user_id : get_current_user_id();

    $role = WeDevs\PM\User\Models\User_Role::with('role')
        ->where( 'project_id', $project_id )
        ->where( 'user_id', $user_id )
        ->first();

    if ( $role ) {
        return $role->role->slug;
    }

    return false;
}

function wedevs_pm_get_role_caps( $project_id, $role ) {
    $caps = wedevs_pm_pro_get_project_capabilities( $project_id );

    if ( !empty( $caps[$role] ) ) {
        return $caps[$role];
    }

    return [];
}

function wedevs_pm_is_manager( $project_id, $user_id = false ) {
    $user_id = $user_id ? $user_id : get_current_user_id();

    $role = wedevs_pm_get_role( $project_id, $user_id );

    return $role == 'manager' ? true : false;
}

/**
 * Returns true if current user has the manager role (role_id=1) in any project.
 * Used to gate global pages (Sprints) that project managers should access,
 * mirroring Vue's canCreateSprint() logic.
 */
function wedevs_pm_current_user_is_manager_anywhere( $user_id = false ) {
    $user_id = $user_id ? intval( $user_id ) : get_current_user_id();

    if ( wedevs_pm_has_manage_capability( $user_id ) ) {
        return true;
    }

    global $wpdb;
    $table = $wpdb->prefix . 'pm_role_user';
    $count = $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM {$table} WHERE user_id = %d AND role_id = 1",
        $user_id
    ) );

    return intval( $count ) > 0;
}

/**
 * Checking for PM_Admin capability
 * @param  boolean $user_id
 * @return [type]
 */
function wedevs_pm_has_admin_capability( $user_id = false ) {

    $user_id = $user_id ? intval( $user_id ) : get_current_user_id();
    
    if ( user_can( $user_id, 'manage_options' ) ) {
        return true;
    }
    
    if ( user_can( $user_id, wedevs_pm_admin_cap_slug() ) ) {
        return true;
    }     
    
    return false;
}

/**
 * Checking for PM_Managre capability
 * @param  boolean $user_id
 * @return [type]
 */
function wedevs_pm_has_manage_capability( $user_id = false ) {

    $user_id = $user_id ? intval( $user_id ) : get_current_user_id();
    $user    = get_user_by( 'id', $user_id );

    if ( wedevs_pm_has_admin_capability() ) {
        return true;
    }
    
    if ( user_can( $user_id, wedevs_pm_manager_cap_slug() ) ) {
        return true;
    }    

    return false;
}

/**
 * Permission checking for outside of projects
 * @param  boolean $cap
 * @param  boolean $user_id
 * @return [type]
 */
function wedevs_pm_user_can_access( $cap = false, $user_id = false ) {
    $user_id = $user_id ? $user_id : get_current_user_id();
    $cap = empty( $cap ) ? wedevs_pm_manager_cap_slug() : $cap;

    if ( wedevs_pm_has_manage_capability() ) {
        return true;
    }

    if ( user_can( $user_id, $cap ) ) {
        return true;
    }

    return false;
}
/**
 * Permission checking for inside a project
 * @param  [type]  $cap
 * @param  [type]  $project_id
 * @param  boolean $user_id
 * @return [type]
 */
function wedevs_pm_user_can( $cap, $project_id, $user_id = false ) {
    $user_id = $user_id ? $user_id : get_current_user_id();

    $cache_key  = 'pm_user_can-' . md5( serialize( [
        'cap'        => $cap,
        'project_id' => $project_id,
        'user_id'    => $user_id
    ] ) );

    $items  = wp_cache_get( $cache_key, 'pm' );

    if ( false === $items ) {
        if ( wedevs_pm_has_manage_capability( $user_id ) ) {
            return true;
        }

        if ( ! wedevs_pm_is_user_in_project( $project_id, $user_id ) ) {
            return false;
        }

        if ( wedevs_pm_is_manager( $project_id, $user_id ) ) {
            return true;
        }

        $role = wedevs_pm_get_role( $project_id, $user_id );
        
        if ( !$role ) {
            return false;
        }

        if ( $cap === 'view_project' ) {
            return true;
        }

        $role_caps = wedevs_pm_get_role_caps( $project_id, $role );

        if ( isset( $role_caps[$cap] ) ) {
            return $role_caps[$cap];
        }

        wp_cache_set( $cache_key, $items, 'pm' );
    }

    return false;
}

function wedevs_pm_has_project_create_capability( $user_id = false ) {
    return wedevs_pm_user_can_access( wedevs_pm_manager_cap_slug() );
}

function wedevs_pm_has_project_managing_capability( $project_id, $user_id = false ) {
    if ( wedevs_pm_has_manage_capability( $user_id ) ) {
        return true;
    }
    if ( wedevs_pm_is_manager( $project_id, $user_id ) ) {
        return true;
    }

    return false;
}

function wedevs_pm_user_can_complete_task( $task, $user_id = false ) {
    if(!$task) {
        return false;
    }
    $user_id = $user_id ? $user_id: get_current_user_id();

    if ( wedevs_pm_has_manage_capability( $user_id ) ) {
        return true;
    }

    if ( wedevs_pm_is_manager( $task->project_id, $user_id ) ) {
        return true;
    }

    if ( $task->created_by == $user_id ) {
        return true;
    }

    $assignees = $task->assignees->toArray(); //pluck( 'assigned_to' )->all();
    $assignees = wp_list_pluck( $assignees, 'assigned_to' );
    $in_array = in_array( $user_id, $assignees );

    if ( !empty( $in_array ) ) {
        return true;
    }

    return false;
}

/**
 * What type of request is this?
 *
 * @param  string $type admin, ajax, cron or frontend.
 * @return bool
 */
function wedevs_pm_is_request( $type ) {
    switch ( $type ) {
        case 'admin' :
            return is_admin();
        case 'ajax' :
            return defined( 'DOING_AJAX' );
        case 'cron' :
            return defined( 'DOING_CRON' );
        case 'frontend' :
            return ( ! is_admin() || defined( 'DOING_AJAX' ) ) && ! defined( 'DOING_CRON' );
        default :
            return false;
    }
}

/**
 * The main logging function
 *
 * @since 0.1
 * @uses error_log
 * @param string $type type of the error. e.g: debug, error, info
 * @param string $msg
 */
function wedevs_pm_log( $type = '', $msg = '' ) {
    $ouput_path = wedevs_pm_config( 'frontend.patch' );

    if ( WP_DEBUG == true ) {
        $msg = sprintf( "[%s][%s] %s\n", gmdate( 'd.m.Y h:i:s' ), $type, print_r($msg, true) );
        error_log( $msg, 3, $ouput_path . '/tmp/pm-debug.log' );
    }
}

function wedevs_pm_get_translations_for_plugin_domain( $domain, $language_dir = null ) {

    if ( $language_dir == null ) {
        $language_dir  = wedevs_pm_config('frontend.patch') . '/languages/';
    }

    $languages     = get_available_languages( $language_dir );
    $get_site_lang = is_admin() ? get_user_locale() : get_locale();
    $mo_file_name  = $domain .'-'. $get_site_lang;
    $translations  = [];

    if (
        in_array( $mo_file_name, $languages )
            &&
        file_exists( $language_dir . $mo_file_name . '.mo' )
    ) {
        $mo = new MO();
        if ( $mo->import_from_file( $language_dir . $mo_file_name . '.mo' ) ) {
            $translations = $mo->entries;
        }
    }

    return [
        'header'       => isset( $mo ) ? $mo->headers : '',
        'translations' => $translations
    ];
}

/**
 * Returns Jed-formatted localization data.
 *
 * @param  string $domain Translation domain.
 *
 * @return array
 */
function wedevs_pm_get_jed_locale_data( $domain, $language_dir = null ) {
    $plugin_translations = wedevs_pm_get_translations_for_plugin_domain( $domain, $language_dir );
    $translations = get_translations_for_domain( $domain );

    $locale = array(
        'domain'      => $domain,
        'locale_data' => array(
            $domain => array(
                '' => array(
                    'domain' => $domain,
                    'lang'   => is_admin() ? get_user_locale() : get_locale(),
                ),
            ),
        ),
    );

    if ( ! empty( $translations->headers['Plural-Forms'] ) ) {
        $locale['locale_data'][ $domain ]['']['plural_forms'] = $translations->headers['Plural-Forms'];
    } else if ( ! empty( $plugin_translations['header']['Plural-Forms'] ) ) {
        $locale['locale_data'][ $domain ]['']['plural_forms'] = $plugin_translations['header']['Plural-Forms'];
    }

    $entries = array_merge( $plugin_translations['translations'], $translations->entries );

    foreach ( $entries as $msgid => $entry ) {
        $locale['locale_data'][ $domain ][ $msgid ] = $entry->translations;
    }
    return $locale;
}

function wedevs_pm_tb_prefix() {
    global $wpdb;

    return $wpdb->prefix;
}

/**
 * Displays tasks, messages, milestones contents. Removed `the_content` filter
 * and applied other filters due to conflicts created by other plugins.
 *
 * @param string $content
 * @return string
 */
function wedevs_pm_get_content( $content ) {
    if (empty($content)) {
        return $content;
    }

    $content = apply_filters( 'wedevs_pm_get_content', $content );

    return $content;
}

function wedevs_pm_filter_content_url( $content ) {
    if (empty($content)) {
        return $content;
    }

    $content = apply_filters( 'wedevs_pm_get_content_url', $content );

    return $content;
}

function wedevs_pm_get_user_url( $user_id, $is_admin ) {
    $is_admin = $is_admin ? 'admin' : 'frontend';
    $pm_base  = wedevs_pm_get_project_page($is_admin);
    $user_url = $pm_base . '#/my-tasks';

    return $user_url;
}

function wedevs_pm_get_task_url( $project_id, $list_id, $task_id, $is_admin ) {
    $is_admin = $is_admin ? 'admin' : 'frontend';
    $pm_base  = wedevs_pm_get_project_page($is_admin);
    $task_url = $pm_base . '#/projects/' . $project_id . '/task-lists/' . $list_id . '/tasks/' . $task_id;

    return $task_url;
}

function wedevs_pm_get_discuss_url( $project_id, $discuss_id, $is_admin ) {
    $is_admin = $is_admin ? 'admin' : 'frontend';
    $pm_base  = wedevs_pm_get_project_page( $is_admin );
    $task_url = $pm_base . '#/projects/' . $project_id . '/discussions/' . $discuss_id;

    return $task_url;
}

function wedevs_pm_get_task( $task_id ) {
    $task = Task::with('task_lists')
        ->where( 'id', $task_id )
        ->first();

    if ( $task == NULL ) {
        return wedevs_pm_get_response( null,  [
            'message' => __( 'No elements found.', 'wedevs-project-manager' )
        ] );
    }

    $resource = new Item( $task, new Task_Transformer );

    return wedevs_pm_get_response( $resource );
}

function wedevs_pm_get_file_download_url( $project_id, $user_id, $file_id ) {
    return get_rest_url() . 'pm/v2/projects/' . $project_id . '/files/' . $file_id . '/users/' . $user_id . '/download';
}

function wedevs_pm_get_list_url( $project_id, $list_id, $is_admin ) {

    $is_admin = $is_admin ? 'admin' : 'frontend';
    $pm_base  = wedevs_pm_get_project_page( $is_admin );
    $list_url = $pm_base . '#/projects/' . $project_id . '/task-lists';

    return $list_url;
}

function wedevs_pm_get_front_end_project_page() {
    $pages   = get_option( 'pm_pages', [] );
    $project = empty( $pages['project'] ) ? '' : absint( $pages['project'] );

    if ( $project ) {
        return get_permalink( $project );
    }

    return '';
}

function wedevs_pm_get_project_page( $type = false ) {

    if ( $type == 'admin' ) {
        return admin_url( 'admin.php?page=pm_projects' );
    }

    if ( $type == 'frontend' ) {
        return wedevs_pm_get_front_end_project_page();
    }

    if ( wedevs_pm_is_request( 'admin' ) ) {
        return admin_url( 'admin.php?page=pm_projects' );
    }

    if ( wedevs_pm_is_request( 'frontend' ) ) {
        return wedevs_pm_get_front_end_project_page();
    }
}

function wedevs_pm_total_projects() {
    $project = Project::count();
    return $project;
}

function wedevs_pm_total_task() {
    $task = Task::count();
    return $task;
}

function wedevs_pm_total_task_list() {
    $task_list = Task_List::count();
    return $task_list;
}

function wedevs_pm_total_milestone() {
    $milestone = Milestone::count();
    return $milestone;
}

function wedevs_pm_total_message() {
    $message = Discussion_Board::count();
    return $message;
}
/**
* Get current IP
*
* @since 1.0.0
*
* @return string IP address
**/
function wedevs_pm_get_ip() {
    $ipaddress = '';

    if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
        $ipaddress = wp_unslash( $_SERVER['HTTP_CLIENT_IP'] ); //phpcs:ignore
    } else if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
        $ipaddress = wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ); //phpcs:ignore
    } else if ( isset( $_SERVER['HTTP_X_FORWARDED'] ) ) {
        $ipaddress = wp_unslash( $_SERVER['HTTP_X_FORWARDED'] ); //phpcs:ignore
    } else if ( isset( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
        $ipaddress = wp_unslash( $_SERVER['HTTP_FORWARDED_FOR'] ); //phpcs:ignore
    } else if ( isset( $_SERVER['HTTP_FORWARDED'] ) ) {
        $ipaddress = wp_unslash( $_SERVER['HTTP_FORWARDED'] ); //phpcs:ignore
    } else if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
        $ipaddress = wp_unslash( $_SERVER['REMOTE_ADDR'] ); //phpcs:ignore
    } else {
        $ipaddress = 'UNKNOWN';
    }

    return $ipaddress;
}

function wedevs_pm_get_capabilities() {

    return [
        'Message Create',
        'Message Private',
        'Task List Create',
        'Task List Private',
        'Milestone Create',
        'Milestone Private',
        'Task Create',
        'Task Private',
        'File Create',
        'File Private',
    ];
}

function wedevs_pm_get_capabilities_relation( $role ) {

    $caps = [
        'create_message'         => 1,
        'view_private_message'   => 2,
        'create_list'            => 3,
        'view_private_list'      => 4,
        'create_milestone'       => 5,
        'view_private_milestone' => 6,
        'create_task'            => 7,
        'view_private_task'      => 8,
        'create_file'            => 9,
        'view_private_file'      => 10
    ];

    return $caps[$role];
}

function wedevs_pm_default_cap( $cap_id = false ) {
    $pm_caps =  [
        '1'  => 'create_message',
        '2'  => 'view_private_message',
        '3'  => 'create_list',
        '4'  => 'view_private_list',
        '5'  => 'create_milestone',
        '6'  => 'view_private_milestone',
        '7'  => 'create_task',
        '8'  => 'view_private_task',
        '9'  => 'create_file',
        '10' => 'view_private_file'
    ];

    if ( $cap_id ) {
        return $pm_caps[$cap_id];
    }

    return $pm_caps;
}

function wedevs_pm_default_manager_caps() {
    return [
        'create_message'         => true,
        'view_private_message'   => true,
        'create_list'            => true,
        'view_private_list'      => true,
        'create_task'            => true,
        'view_private_task'      => true,
        'create_milestone'       => true,
        'view_private_milestone' => true,
        'create_file'            => true,
        'view_private_file'      => true
    ];
}

function wedevs_pm_default_co_caps() {
    return [
        'create_message'         => true,
        'view_private_message'   => true,
        'create_list'            => true,
        'view_private_list'      => true,
        'create_task'            => true,
        'view_private_task'      => true,
        'create_milestone'       => true,
        'view_private_milestone' => true,
        'create_file'            => true,
        'view_private_file'      => true
    ];
}

function wedevs_pm_default_client_caps() {
    return [
        'create_message'         => true,
        'view_private_message'   => false,
        'create_list'            => true,
        'view_private_list'      => false,
        'create_task'            => true,
        'view_private_task'      => false,
        'create_milestone'       => true,
        'view_private_milestone' => false,
        'create_file'            => true,
        'view_private_file'      => false
    ];
}

function wedevs_pm_get_prepare_format( $ids, $is_string = false ) {

    
    $ids = wedevs_pm_get_prepare_data( $ids );

    // how many entries will we select?
    $how_many = count( $ids );

    // prepare the right amount of placeholders
    // if you're looing for strings, use '%s' instead
    if( $is_string ) {
        $placeholders = array_fill( 0, $how_many, '%s' );
    } else {
        $placeholders = array_fill( 0, $how_many, '%d' );
    }

    // glue together all the placeholders...
    // $format = '%d, %d, %d, %d, %d, [...]'
    $format = implode( ', ', $placeholders );

    return $format;
}

function wedevs_pm_get_prepare_data( $args, $delimiter = ',' ) {

    $new = [];

    if ( is_array( $args ) ) {
        foreach ( $args as $date_key => $value ) {
            if ( empty( $value ) ) {
                continue;
            }

            $new[trim($date_key)] = trim( $value );
        }
    }

    if ( ! is_array( $args ) ) {
        $args = explode( $delimiter, $args );

        foreach ( $args as $date_key => $value ) {
            if ( empty( $value ) ) {
                continue;
            }

            $new[trim($date_key)] = trim( $value );
        }
    }

    return $new;
}

/**
 * Clean variables using pm_clean. Arrays are cleaned recursively.
 * Non-scalar values are ignored.
 *
 * @param string|array $var Data to sanitize.
 * @return string|array
 */
function wedevs_pm_clean( $var ) {
    if ( is_array( $var ) ) {
        return array_map( 'pm_clean', $var );
    } else {
        return is_scalar( $var ) ? sanitize_text_field( wp_unslash( $var ) ) : $var;
    }
}

/**
 * Get Dashboard slug
 *
 * @since 1.0.0
 * @return string
 */
function wedevs_pm_frontend_slug() {
    $slug = get_option( 'pm_frontend_slug' );
    if ( ! $slug ) {
        $slug = 'pm';
    }

    return apply_filters( 'wedevs_pm_frontend_slug', sanitize_title( $slug ) );
}

/**
 * Get dashboard url
 *
 * @return string
 */
function wedevs_pm_frontend_url() {
    $site_url       = get_site_url();
    $dashboard_slug = ltrim( wedevs_pm_frontend_slug(), '/' );

    return trailingslashit( $site_url ) . $dashboard_slug;
}

/**
 * Get dashboard title
 *
 * @return string
 */
function wedevs_pm_dashboard_title() {
    $dashboard_title = get_option( 'pm_frontend_dashboard_title' );

    if ( ! $dashboard_title ) {
        $dashboard_title = __( 'Project Manager', 'wedevs-project-manager' );
    }

    return apply_filters( 'wedevs_pm_dashboard_title', $dashboard_title );
}

/**
 * Get frontend query var
 *
 * @return string
 */
function wedevs_pm_register_query_var() {
    return apply_filters( 'wedevs_pm_frontend_query_var', 'pm_dashboard' );
}

/**
 * Get HTML wrap
 *
 * @return string
 */
function wedevs_pm_root_element() {
    $id = wedevs_pm_root_element_id();
    return apply_filters( 'wedevs_pm_root_element', '<div id="'. $id .'"></div>' );
}

/**
 * Get HTML wrap id
 *
 * @return string
 */
function wedevs_pm_root_element_id() {
    return apply_filters( 'wedevs_pm_root_element_id', 'wedevs-pm' );
}

/**
 * Get admin slug
 *
 * @return string
 */
function wedevs_pm_admin_slug() {
    return apply_filters( 'wedevs_pm_admin_slug', 'pm_projects' );
}

/**
 * Get admin url
 *
 * @return string
 */
function wedevs_pm_admin_url() {
    $slug = wedevs_pm_admin_slug();
    return apply_filters( 'wedevs_pm_admin_url', admin_url( "admin.php?page={$slug}" ) );
}

/**
 * Dashboard Logo
 *
 * @return void
 */
function wedevs_pm_dashboard_logo() {
    // $logo = get_option( 'pm_frontend_logo' );
    // if ( $logo ) {
    //     return wp_get_attachment_url( $logo );
    // }

    // return ERP_DASHBOARD_ASSETS . '/images/pm-logo.png';
}

function wedevs_pm_active_for_network() {
    
    $plugins     = get_plugins();
    $plugin_path = false;
    
    foreach ( $plugins as $path => $plugin ) {
        if ( $plugin['TextDomain'] == 'wedevs-project-manager' ) {
            $plugin_path = $path;
        }
    }

    if ( empty( $plugin_path ) ) {
        return false;
    }

    if ( is_plugin_active_for_network( $plugin_path ) ) {
        return true;
    }

    return false;
}

function wedevs_pm_user_meta_key() {
    global $wpdb;

    return $wpdb->prefix . 'capabilities';
}

function wedevs_pm_can_create_user_at_project_create_time() {
    return apply_filters( 'wedevs_pm_can_create_user_at_project_create_time', true );
}

function wedevs_pm_get_estimation_type() { 
    if ( ! function_exists( 'wedevs_pm_pro_is_module_active' ) ) {
        return 'task';
    }

    if ( wedevs_pm_pro_is_module_active( 'Sub_Tasks/Sub_Tasks.php' ) ) {
        return 'subtask';
    }

    // $db_est_type = wedevs_pm_get_setting( 'estimation_type' );

    // if ( empty( $db_est_type ) ) {
    //     return 'task';
    // }

    return 'task';
}

function wedevs_pm_is_active_time_tracker_module() { 
    if ( ! function_exists( 'wedevs_pm_pro_is_module_active' ) ) {
        return false;
    }

    if ( wedevs_pm_pro_is_module_active( 'Time_Tracker/Time_Tracker.php' ) ) {
        return true;
    }

    return false;
}

function wedevs_pm_second_to_time( $seconds ) {
    $total_second = $seconds;
    // extract hours
    $hours = floor( $seconds / (60 * 60) );

    // extract minutes
    $divisor_for_minutes = $seconds % (60 * 60);
    $minutes = floor( $divisor_for_minutes / 60 );

    // extract the remaining seconds
    $divisor_for_seconds = $divisor_for_minutes % 60;
    $seconds = ceil( $divisor_for_seconds );

    // return the final array
    $obj = array(
        'hour' => str_pad( (int) $hours, 2, '0', STR_PAD_LEFT ),
        'minute' => str_pad( (int) $minutes, 2, '0', STR_PAD_LEFT ),
        'second' => str_pad( (int) $seconds, 2, '0', STR_PAD_LEFT ),
        'total_second' => $total_second
    );

    return $obj;
}

/**
 * [pm_get_projects description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_projects( $params = [] ) {
     return WeDevs\PM\Project\Helper\Project::get_results( $params );
}

/**
 * [pm_get_task_lists description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_task_lists( $params = [] ) {
     return \WeDevs\PM\Task_List\Helper\Task_List::get_results( $params );
}

/**
 * [pm_get_tasks description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_tasks( $params = [] ) {
     return \WeDevs\PM\task\Helper\Task::get_results( $params );
}

/**
 * [pm_get_tasks description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_activities( $params = [] ) {
     return \WeDevs\PM\Activity\Helper\Activity::get_results( $params );
}

/**
 * [pm_get_milestones description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_milestones( $params = [] ) {
     return \WeDevs\PM\Milestone\Helper\Milestone::get_results( $params );
}

/**
 * [pm_get_discussions description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_discussions( $params = [] ) {
     return \WeDevs\PM\Discussion_Board\Helper\Discussion_Board::get_results( $params );
}

/**
 * [pm_get_comments description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_comments( $params = [] ) {
     return \WeDevs\PM\Comment\Helper\Comment::get_results( $params );
}

/**
 * [pm_get_files description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_files( $params = [] ) {
     return \WeDevs\PM\File\Helper\File::get_results( $params );
}

/**
 * [pm_get_users description]
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_get_users( $params = [] ) {
     return \WeDevs\PM\User\Helper\User::get_results( $params );
}

/**
 * check the query is single data or not
 * @param  array|string $params
 * @return [type]
 */
function wedevs_pm_is_single_query( $params ) {
    if ( empty( $params['id'] ) ) {
        return false;
    }

    if ( is_array( $params['id'] ) ) {
        return false;
    }

    $id = wedevs_pm_get_prepare_data( $params['id'] );
    
    if ( count( $id ) == 1 ) {
        return true;
    }

    return false;
}

function wedevs_pm_api_namespace() {
    return wedevs_pm_config( 'app.slug' ) . '/v' . wedevs_pm_config( 'app.api' );
}

function wedevs_pm_current_user_can_update_core() {
    if ( is_multisite() ) {
        if ( is_main_site() && current_user_can( 'activate_plugins' ) ) {
            return true;
        } else { 
            return false; 
        }
    }

    if ( current_user_can( 'activate_plugins' ) ) {
        return true;
    }

    return false;
}

/**
 * check value for boolean
 * 
 * @param  string|boolean $val
 * 
 * @return [type]
 */
function wedevs_pm_is_true ( $val ) {
    
    if ( is_string( $val ) ) {
        return $val == 'true' || $val == '1' ? true : false;
    }

    return (int) $val ? true : false;
}

/**
 * [pm_pro_progress_page_slug description]
 * @return [type]
 */
function wedevs_pm_admin_cap_slug() {
    return apply_filters( 'wedevs_pm_admin_capability_slug', 'pm_admin' );
}

/**
 * [pm_pro_reports_page_slug description]
 * @return [type]
 */
function wedevs_pm_manager_cap_slug() {
    return apply_filters( 'wedevs_pm_manager_capability_slug', 'pm_manager' );
}

/**
 * [pm_pro_menu_access_capabilities description]
 * @param  boolean $cap
 * @return [type]
 */
function wedevs_pm_access_capabilities( $cap = false ) {
    $caps = [
        wedevs_pm_admin_cap_slug()   => __( 'PM Admin', 'wedevs-project-manager' ),
        wedevs_pm_manager_cap_slug() => __( 'PM Manager', 'wedevs-project-manager' ),
    ];

    $caps = apply_filters( 'wedevs_pm_access_capabilities', $caps );

    return empty( $cap ) ? $caps : $caps[$cap];
}


function wedevs_pm_validate_assignee( $assignees){
    
    if ( empty( $assignees ) ) {
            return [];
    }
    
    if ( !is_array( $assignees ) ) {
            return [];
    }

    foreach ( $assignees as &$assignee ) {
        // Sanitize user_id and role_id
        $assignee['user_id'] = absint( $assignee['user_id'] );
        $assignee['role_id'] = absint( $assignee['role_id'] );
        
        // validate user_id exists
        $user = get_user_by( 'id', $assignee['user_id'] );
        if ( ! $user ) {
            continue;
        }
        
        // validate role_id is a valid role in your system
        if ( ! get_role( $assignee['role_id'] ) ) {
            continue;
        }
    }

    return $assignees;
}
                                                                                    
/**
 * Load Headway widget badge script
 *
 * @since 2.7.0
 *
 * @param string $selector The CSS selector for the headway badge element
 * @return void
 */
function wedevs_pm_load_headway_badge( $selector = '#pm-headway-icon' ) {
    wp_enqueue_script( 'pm-headway' );
    ?>
    <script>
        (function() {
            var pmHeadwaySelector = '<?php echo esc_js( $selector ); ?>';

            function pmInitHeadway() {
                window.HW_config = {
                    selector: pmHeadwaySelector,
                    account: 'yo9n07',
                    callbacks: {
                        onWidgetReady: function ( widget ) {
                            // Hide badge dot when no unseen items (only the small dot, not the popup)
                            if ( widget.getUnseenCount() === 0 ) {
                                var badge = document.querySelector('#HW_badge');
                                if (badge) badge.style.display = 'none';
                            }
                        }
                    }
                };

                window.Headway.init( window.HW_config );
            }

            // Use MutationObserver to detect when React mounts the target element
            function pmWaitForHeadway() {
                if ( typeof window.Headway === 'undefined' ) return;

                var target = document.querySelector( pmHeadwaySelector );
                if ( target ) {
                    pmInitHeadway();
                    return;
                }

                // Observe DOM for the React-rendered element
                var observer = new MutationObserver( function( mutations, obs ) {
                    if ( document.querySelector( pmHeadwaySelector ) ) {
                        obs.disconnect();
                        pmInitHeadway();
                    }
                });

                observer.observe( document.body, { childList: true, subtree: true } );
            }

            if ( document.readyState === 'complete' ) {
                pmWaitForHeadway();
            } else {
                window.addEventListener( 'load', pmWaitForHeadway );
            }
        })();
    </script>

    <?php
}
