<?php

namespace LoftyIDX\includes\providers;

use LoftyIDX\includes\LoftyIDXRouter;
use Twig\Loader\FilesystemLoader;
use Twig\Environment;
use LoftyIDX\includes\extensions\LoftyIDXTwigScriptExtension;
use LoftyIDX\includes\extensions\LoftyIDXTwigFunctionExtension;

defined('ABSPATH') || exit;

class LoftyIDXTemplateServiceProvider implements LoftyIDXBaseProvider
{
    protected $container = null;

    public $viewer = null; // template loader

    public function __construct($container)
    {
        $this->container = $container;
    }

    public function setup_template_engine()
    {
        $is_dev_mode = defined('LOFTY_ENABLE_TEMPLATE_CACHE') && LOFTY_ENABLE_TEMPLATE_CACHE;

        // Get cache path from configuration, with fallback to plugin directory
        $cache_path = $this->getCachePath();

        $loader = new FilesystemLoader(LOFTY_IDX_PATH . 'templates');
        $this->viewer = new Environment($loader, [
            'cache' => $cache_path,
            'auto_reload' => $is_dev_mode,
            'debug' => $is_dev_mode
        ]);

        $this->viewer->addExtension(new LoftyIDXTwigFunctionExtension());
        $this->viewer->addExtension(new LoftyIDXTwigScriptExtension($this->viewer));

        return $this->viewer;
    }

    /**
     * Get the template cache path, ensuring it exists and is writable
     * @return string The cache path to use
     */
    public function getCachePath()
    {
        // Use cache path from environment variable if configured
        $custom_cache_path = !empty(LOFTY_TEMPLATE_CACHE_PATH) ? trim(LOFTY_TEMPLATE_CACHE_PATH) : '';
        
        // Determine primary cache path
        if (!empty($custom_cache_path)) {
            // Handle both absolute and relative paths from environment
            if ($this->isAbsolutePath($custom_cache_path)) {
                $primary_cache_path = wp_normalize_path($custom_cache_path);
            } else {
                $primary_cache_path = wp_normalize_path(ABSPATH . ltrim($custom_cache_path, '/'));
            }
        } else {
            $primary_cache_path = LOFTY_IDX_PATH . 'cache';
        }

        // Try to use the primary cache path
        if ($this->ensureCacheDirectory($primary_cache_path)) {
            return $primary_cache_path;
        }

        // If primary path fails, try wp-content/cache/lofty-idx as fallback
        $wp_content_cache = WP_CONTENT_DIR . '/cache/lofty-idx';
        if ($this->ensureCacheDirectory($wp_content_cache)) {
            return $wp_content_cache;
        }

        // Final fallback to plugin directory
        $fallback_cache_path = LOFTY_IDX_PATH . 'cache';
        if ($this->ensureCacheDirectory($fallback_cache_path)) {
            return $fallback_cache_path;
        }

        // If all else fails, disable cache by returning false
        return false;
    }

    /**
     * Checks if a path is absolute.
     * @param string $path The path to check.
     * @return bool True if absolute, false otherwise.
     */
    private function isAbsolutePath($path)
    {
        // Check if path starts with a slash or a drive letter (Windows)
        return (strpos($path, '/') === 0 || (strpos($path, ':') !== false && strpos($path, ':') === 1));
    }

    /**
     * Ensure cache directory exists and is writable
     * @param string $path The directory path to check/create
     * @return bool True if directory is ready to use, false otherwise
     */
    private function ensureCacheDirectory($path)
    {
        try {
            // Check if directory exists
            if (!is_dir($path)) {
                // Try to create the directory
                if (!wp_mkdir_p($path)) {
                    return false;
                }
            }

            // Check if directory is writable
            if (!is_writable($path)) {
                return false;
            }

            // Create .htaccess file to protect cache directory
            $htaccess_file = $path . '/.htaccess';
            if (!file_exists($htaccess_file)) {
                $htaccess_content = "# Lofty IDX Template Cache\n";
                $htaccess_content .= "# Deny access to cache files\n";
                $htaccess_content .= "<Files \"*\">\n";
                $htaccess_content .= "    Require all denied\n";
                $htaccess_content .= "</Files>\n";
                
                file_put_contents($htaccess_file, $htaccess_content);
            }

            return true;
        } catch (Exception $e) {
            // Log error if logging is available
            if (function_exists('error_log')) {
                error_log('Lofty IDX: Failed to setup cache directory: ' . $e->getMessage());
            }
            return false;
        }
    }

    public function register()
    {
        $this->init_hooks();
        $this->setup_template_engine();
        $this->removeDefaultTitle();
    }

    public function removeDefaultTitle()
    {
        if(is_admin()) return;
        $accept = $_SERVER['HTTP_ACCEPT'] ?? '';
        $is_html_request = strpos($accept, 'text/html') !== false;
        if ($is_html_request) {
            $current_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
            $current_page_key = $_GET['pageKey'] ?? '';
            $routes = LoftyIDXRouter::getRoutes();
            $paths = [];
            $page_keys = [];
            foreach ($routes as $route) {
                $paths[] = trim($route['url'], '/');
                $page_keys[] = $route['pageKey'];
            }
            if(in_array($current_path, $paths) || in_array($current_page_key, $page_keys)) {
                add_action('after_setup_theme', function() {
                    remove_theme_support('title-tag');
                    remove_action('wp_head', '_wp_render_title_tag', 1);
                }, 100);
            }
        }
    }

    public function init_hooks()
    {
        add_action('init', [$this, 'add_rewrite_rules']);
        add_filter('query_vars', [$this, 'register_query_vars']);
        add_filter('template_include', array($this, 'template_load'));
        add_action('wp_head', array($this, 'set_header'));
        
        // Check for pending flush on each page load
        add_action('wp_loaded', [$this, 'check_and_flush_rewrite_rules']);
        
        // Set flush flags instead of immediate flushing
        // This avoids timing issues where deactivation hooks run after init actions
        add_action('lofty_idx_flush_rewrite_rules', [$this, 'set_flush_flag']);
        add_action('lofty_idx_uninstall_rewrite_rules', [$this, 'set_flush_flag']);
        add_action('after_switch_theme', [$this, 'set_flush_flag']);
        
        add_action('admin_enqueue_scripts', [$this, 'add_custom_scripts'], 1);  // for admin
        add_action('wp_enqueue_scripts', [$this, 'add_custom_scripts'], 1); // for frontend
    }

    public function set_header()
    {
        echo '<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0 " />';
    }

    public function template_load($template)
    {
        global $wp_query;
        if (!empty($wp_query->query_vars['lofty_page']) || !empty($wp_query->query_vars['name'])) {
            // when page url dynamically changed, lofty_page maybe null, name param maybe not normalized
            // http://127.0.0.1:8000/xxxx?pagekey=search&name=listing
            $page = $wp_query->query_vars['lofty_page'] ?? $wp_query->query_vars['name'];
            $routes = LoftyIDXRouter::getRoutes();
            
            // if pageKey in query string, replace path and redirect url
            $pageKey=isset($_GET['pageKey']) ? sanitize_key($_GET['pageKey']) : '';

            $target_route=null;
            if($pageKey && in_array($pageKey, LoftyIDXRouter::listingPageKeys)){
                // when have page key, find target route rule
                $targets=array_filter($routes, function($route, $key) use ($pageKey) {
                    return isset($route['pageKey']) && ($route['pageKey'] === $pageKey);
                }, ARRAY_FILTER_USE_BOTH);
                if(count($targets) > 0){
                    // $target is like: [key=> $route]
                    $target_route=array_values($targets)[0];
                    // check if url stale and should redirect
                    $pattern=$target_route['pattern'];
                    if (!preg_match("#$pattern#", $this->get_current_url_path())) {
                        $this->replace_url($target_route['url']);
                        return;
                    }
                 
                }
            } else {
                if(array_key_exists($page, $routes)){
                    $target_route=$routes[$page];
                } else {
                    $targets = array_filter($routes, function ($route, $key) use ($page) {
                        // dynamic page url
                        $pattern = $route['pattern'];
                        return !!preg_match("#$pattern#", $page);
                    }, ARRAY_FILTER_USE_BOTH);
                    if(count($targets) > 0){
                        $target_route=array_values($targets)[0];
                    }
                }
            }
            if(is_array($target_route)){
                $template_file = LOFTY_IDX_PATH . 'templates/' .   $target_route["template"];
                if (file_exists($template_file)) {
                    $wp_query->is_404 = false;
                    status_header(200);
                    return $template_file;
                }
            }
        } 
        return $template;
    }

    public function get_current_url_path()
    {
         // current request url
         $url = home_url(add_query_arg());
         $parsed_url = wp_parse_url($url);
         return trim($parsed_url['path'], '/');
    }

    public function replace_url($new_pathname = '', $redirect = true)
    {
        // current request url
        $url = home_url(add_query_arg());

        // Parse the URL into components
        $parsed_url = wp_parse_url($url);

        // Parse the query string into an array
        parse_str($parsed_url['query'], $query_params);

        // don't remove pageKey parameter
        // unset($query_params['pageKey']);

        // Build new query string
        $new_query = http_build_query($query_params);

        // Replace old pathname with new pathname in the path
        $old_path = trim($parsed_url['path'], '/');
        
        // Handle both cases: with and without trailing slash
        $path = $parsed_url['path'];
        if ($path === "/$old_path") {
            // Exact match without trailing slash: /listing -> /map-search
            $new_path = "/$new_pathname";
        } elseif (strpos($path, "/$old_path/") !== false) {
            // Match with trailing slash: /listing/something -> /map-search/something
            $new_path = str_replace("/$old_path/", "/$new_pathname/", $path);
        } else {
            // No match, keep original path
            $new_path = $path;
        }
        // Reconstruct the URL
        $new_url = $parsed_url['scheme'] . '://' .
            $parsed_url['host'] .
            (isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '') .
            $new_path .
            ($new_query ? '?' . $new_query : '');
        if($redirect){
            wp_safe_redirect($new_url);
            exit;
        }
        return $new_url;
    }

    public function add_custom_scripts()
    {
        $handle = 'lofty-idx-utils';
        wp_enqueue_script(
            $handle, 
            LOFTY_IDX_URL . 'public/js/lofty-idx-utils.js', 
            [], 
            '0.1.0', 
            'defer'
        );
    
        // Pass plugin root URL to JavaScript
        wp_localize_script(
            $handle, 
            'LoftyIdxUtils', 
            [
                'plugin_root_url' => LOFTY_IDX_URL,
                'ajax_url' => admin_url('admin-ajax.php'),
                'ajax_nonce'=> wp_create_nonce('lofty-idx-ajax-nonce')
            ]
        );
    }

    public function add_rewrite_rules()
    {
        if(wp_doing_ajax()) {
            return;
        }
        $request_uri = $_SERVER['REQUEST_URI'];
        $static_extensions = ['.css', '.js', '.jpg', '.jpeg', '.png','.ico', '.map', '.json'];
        foreach ($static_extensions as $ext) {
            if (str_ends_with($request_uri, $ext)) {
                return;
            }
        }
        
        $routes = LoftyIDXRouter::getRoutes();
        foreach ($routes as $route) {
            add_rewrite_rule(
                $route['pattern'],
                $route['match'],
                'top'
            );
        }
        // Don't flush on every page load - only when really needed
    }

    public function register_query_vars($vars)
    {
        $allParams = LoftyIDXRouter::parseAllParams();
        foreach ($allParams as $v) {
            $vars[] = $v;
        }
        return $vars;
    }

    /**
     * Set a flag to indicate that rewrite rules should be flushed on next page load
     * 
     * This delayed approach solves timing issues where plugin deactivation hooks
     * run after the init action (when add_rewrite_rule() calls happen).
     * Instead of immediate flush, we set a flag and flush on next page load.
     */
    public function set_flush_flag()
    {
        update_option('lofty_idx_needs_rewrite_flush', true);
    }

    /**
     * Check if rewrite rules need to be flushed and do it if needed
     * 
     * This runs on wp_loaded hook to ensure all rewrite rules are added
     * before we flush them. The flag is reset after successful flush.
     */
    public function check_and_flush_rewrite_rules()
    {
        if (get_option('lofty_idx_needs_rewrite_flush')) {
            flush_rewrite_rules();
            delete_option('lofty_idx_needs_rewrite_flush');
        }
    }
}
