<?php
/**
 * Time Tracking Controller
 *
 * @package Freelance_Studio
 */

class FS_Time_Tracking_Controller {

    /**
     * Handle the request
     */
    public function handle_request() {
        $action = isset($_GET['action']) ? sanitize_text_field($_GET['action']) : 'index';

        switch ($action) {
            case 'add':
            case 'edit':
                $this->form();
                break;
            case 'week':
                $this->week_view();
                break;
            case 'reports':
                $this->reports();
                break;
            // popup_timer is handled early in FS_Admin::handle_popup_timer()
            default:
                $this->index();
                break;
        }
    }

    /**
     * Display time entries list (Timer view)
     */
    public function index() {
        // Get filter values
        $filters = array(
            'client_id' => isset($_GET['client_id']) ? intval($_GET['client_id']) : null,
            'project_id' => isset($_GET['project_id']) ? intval($_GET['project_id']) : null,
            'task_id' => isset($_GET['task_id']) ? intval($_GET['task_id']) : null,
            'activity' => isset($_GET['activity']) ? sanitize_text_field($_GET['activity']) : null,
            'invoiced' => isset($_GET['invoiced']) && $_GET['invoiced'] !== '' ? intval($_GET['invoiced']) : null,
            'date_range' => isset($_GET['date_range']) ? sanitize_text_field($_GET['date_range']) : 'this_year',
        );

        // Calculate date range
        $date_from = null;
        $date_to = null;
        
        switch ($filters['date_range']) {
            case 'today':
                $date_from = gmdate('Y-m-d');
                $date_to = gmdate('Y-m-d');
                break;
            case 'yesterday':
                $date_from = gmdate('Y-m-d', strtotime('-1 day'));
                $date_to = gmdate('Y-m-d', strtotime('-1 day'));
                break;
            case 'this_week':
                $date_from = gmdate('Y-m-d', strtotime('monday this week'));
                $date_to = gmdate('Y-m-d', strtotime('sunday this week'));
                break;
            case 'last_week':
                $date_from = gmdate('Y-m-d', strtotime('monday last week'));
                $date_to = gmdate('Y-m-d', strtotime('sunday last week'));
                break;
            case 'this_month':
                $date_from = gmdate('Y-m-01');
                $date_to = gmdate('Y-m-t');
                break;
            case 'last_month':
                $date_from = gmdate('Y-m-01', strtotime('first day of last month'));
                $date_to = gmdate('Y-m-t', strtotime('last day of last month'));
                break;
            case 'this_year':
                $date_from = gmdate('Y-01-01');
                $date_to = gmdate('Y-12-31');
                break;
            case 'all':
                // No date filter
                break;
        }

        // Pagination
        $per_page = 25;
        $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
        $offset = ($current_page - 1) * $per_page;

        $filter_args = array(
            'client_id' => $filters['client_id'],
            'project_id' => $filters['project_id'],
            'task_id' => $filters['task_id'],
            'activity' => $filters['activity'],
            'invoiced' => $filters['invoiced'],
            'date_from' => $date_from,
            'date_to' => $date_to,
        );

        // Get total count for pagination
        $total_entries = FS_Time_Entry::count_all($filter_args);
        $total_pages = ceil($total_entries / $per_page);

        // Get time entries (paginated)
        $entries = FS_Time_Entry::get_all(array_merge($filter_args, array(
            'orderby' => 'start_time',
            'order' => 'DESC',
            'limit' => $per_page,
            'offset' => $offset,
        )));

        // Get running timer
        $running_timer = FS_Time_Entry::get_running_timer();

        // Get data for filters - all projects (including completed) for filter dropdown
        $clients = FS_Client::get_all(array('orderby' => 'name', 'order' => 'ASC'));
        $projects = FS_Project::get_all(array('orderby' => 'name', 'order' => 'ASC', 'include_archived' => true));
        // Active projects only for timer/quickadd dropdowns (exclude completed, cancelled, archived)
        $active_projects = FS_Project::get_all(array('status' => array('draft', 'pending', 'active', 'on_hold'), 'orderby' => 'name', 'order' => 'ASC'));
        $activity_types = FS_Time_Entry::get_activity_types();
        
        // Only show tasks that have associated time entries (avoids stale recurring duplicates)
        global $wpdb;
        $tasks_table = $wpdb->prefix . 'fs_tasks';
        $time_table = $wpdb->prefix . 'fs_time_entries';
        $tasks = $wpdb->get_results(
            "SELECT DISTINCT tk.id, tk.title
             FROM {$tasks_table} tk
             INNER JOIN {$time_table} te ON te.task_id = tk.id
             ORDER BY tk.title ASC"
        );

        // Get summary stats
        $summary = FS_Time_Entry::get_summary(array(
            'client_id' => $filters['client_id'],
            'project_id' => $filters['project_id'],
            'activity' => $filters['activity'],
            'task_id' => $filters['task_id'],
            'invoiced' => $filters['invoiced'],
            'date_from' => $date_from,
            'date_to' => $date_to,
        ));

        include JEEB_FS_PLUGIN_DIR . 'includes/views/time-tracking/list.php';
    }

    /**
     * Display add/edit form
     */
    public function form() {
        $id = isset($_GET['id']) ? intval($_GET['id']) : 0;
        $entry = $id ? FS_Time_Entry::get($id) : null;

        // Get active projects for dropdown (exclude completed, cancelled, archived)
        $projects = FS_Project::get_all(array('status' => array('draft', 'pending', 'active', 'on_hold'), 'orderby' => 'name', 'order' => 'ASC'));
        
        // If editing, ensure the entry's current project is included even if completed/archived
        if ($entry && !empty($entry->project_id)) {
            $found = false;
            foreach ($projects as $p) {
                if ($p->id == $entry->project_id) {
                    $found = true;
                    break;
                }
            }
            if (!$found) {
                $current_project = FS_Project::get($entry->project_id);
                if ($current_project) {
                    $projects[] = $current_project;
                    usort($projects, function($a, $b) { return strcasecmp($a->name, $b->name); });
                }
            }
        }
        
        $activity_types = FS_Time_Entry::get_activity_types();

        include JEEB_FS_PLUGIN_DIR . 'includes/views/time-tracking/form.php';
    }

    /**
     * Display week view
     */
    public function week_view() {
        // Get week offset from URL
        $week_offset = isset($_GET['week']) ? intval($_GET['week']) : 0;
        
        // Calculate week start/end
        $week_start = gmdate('Y-m-d', strtotime("monday this week {$week_offset} week"));
        $week_end = gmdate('Y-m-d', strtotime("sunday this week {$week_offset} week"));

        // Get entries for the week
        $entries_by_date = FS_Time_Entry::get_by_date_range($week_start, $week_end);

        // Build array of all days in the week
        $days = array();
        $current = strtotime($week_start);
        $end = strtotime($week_end);
        
        while ($current <= $end) {
            $date = gmdate('Y-m-d', $current);
            $days[$date] = array(
                'date' => $date,
                'day_name' => gmdate('l', $current),
                'day_short' => gmdate('D', $current),
                'day_num' => gmdate('j', $current),
                'month' => gmdate('M', $current),
                'entries' => isset($entries_by_date[$date]) ? $entries_by_date[$date] : array(),
                'total_seconds' => 0,
            );
            
            // Calculate total for day
            if (!empty($days[$date]['entries'])) {
                foreach ($days[$date]['entries'] as $entry) {
                    $days[$date]['total_seconds'] += $entry->duration;
                }
            }
            
            $current = strtotime('+1 day', $current);
        }

        // Calculate week totals
        $week_total_seconds = 0;
        $week_billable_seconds = 0;
        foreach ($entries_by_date as $date => $entries) {
            foreach ($entries as $entry) {
                $week_total_seconds += $entry->duration;
                if ($entry->billable) {
                    $week_billable_seconds += $entry->duration;
                }
            }
        }

        // Get running timer
        $running_timer = FS_Time_Entry::get_running_timer();

        // Get projects for quick add
        $projects = FS_Project::get_all(array('status' => array('pending', 'active'), 'orderby' => 'name', 'order' => 'ASC'));
        $activity_types = FS_Time_Entry::get_activity_types();

        include JEEB_FS_PLUGIN_DIR . 'includes/views/time-tracking/week.php';
    }

    /**
     * Display time reports
     */
    public function reports() {
        // Get filter values
        $filters = array(
            'client_id' => isset($_GET['client_id']) ? intval($_GET['client_id']) : null,
            'project_id' => isset($_GET['project_id']) ? intval($_GET['project_id']) : null,
            'date_from' => isset($_GET['date_from']) ? sanitize_text_field($_GET['date_from']) : gmdate('Y-m-01'),
            'date_to' => isset($_GET['date_to']) ? sanitize_text_field($_GET['date_to']) : gmdate('Y-m-d'),
            'group_by' => isset($_GET['group_by']) ? sanitize_text_field($_GET['group_by']) : 'project',
        );

        // Get summary stats
        $summary = FS_Time_Entry::get_summary($filters);

        // Get detailed breakdown
        $breakdown = $this->get_time_breakdown($filters);

        // Get data for filters
        $clients = FS_Client::get_all(array('orderby' => 'name', 'order' => 'ASC'));
        $projects = FS_Project::get_all(array('orderby' => 'name', 'order' => 'ASC'));

        include JEEB_FS_PLUGIN_DIR . 'includes/views/time-tracking/reports.php';
    }

    /**
     * Get time breakdown by grouping
     *
     * @param array $filters Filter parameters
     * @return array Breakdown data
     */
    private function get_time_breakdown($filters) {
        global $wpdb;
        $time_table = $wpdb->prefix . 'fs_time_entries';
        $projects_table = $wpdb->prefix . 'fs_projects';
        $clients_table = $wpdb->prefix . 'fs_clients';

        $where = array('t.end_time IS NOT NULL');
        $values = array();

        if (!empty($filters['client_id'])) {
            $where[] = 'p.client_id = %d';
            $values[] = $filters['client_id'];
        }

        if (!empty($filters['project_id'])) {
            $where[] = 't.project_id = %d';
            $values[] = $filters['project_id'];
        }

        if (!empty($filters['date_from'])) {
            $where[] = 'DATE(t.start_time) >= %s';
            $values[] = $filters['date_from'];
        }

        if (!empty($filters['date_to'])) {
            $where[] = 'DATE(t.start_time) <= %s';
            $values[] = $filters['date_to'];
        }

        $where_clause = implode(' AND ', $where);

        // Group by selection
        switch ($filters['group_by']) {
            case 'client':
                $group_by = 'p.client_id';
                $select_extra = 'c.name as group_name, c.company_name';
                break;
            case 'activity':
                $group_by = 't.activity';
                $select_extra = 't.activity as group_name, NULL as company_name, NULL as client_company_name';
                break;
            case 'date':
                $group_by = 'DATE(t.start_time)';
                $select_extra = 'DATE(t.start_time) as group_name, NULL as company_name, NULL as client_company_name';
                break;
            case 'task':
                $group_by = 't.task_id';
                $select_extra = 'COALESCE(tk.title, \'No task\') as group_name, p.name as project_name, NULL as company_name';
                break;
            case 'project':
            default:
                $group_by = 't.project_id';
                $select_extra = 'p.name as group_name, COALESCE(c.company_name, c.name) as client_name, c.company_name as client_company_name';
                break;
        }

        // Build SQL expression for rounded duration (applies user's time rounding setting)
        $rounding_minutes = intval(get_option('fs_time_rounding', 0));
        $minimum_minutes = intval(get_option('fs_minimum_billable', 0));
        
        if ($minimum_minutes > 0) {
            $min_seconds = $minimum_minutes * 60;
            $tt_duration_expr = "GREATEST(t.duration, {$min_seconds})";
        } else {
            $tt_duration_expr = "t.duration";
        }
        
        if ($rounding_minutes > 0) {
            $rounding_seconds = $rounding_minutes * 60;
            $tt_rounded_duration = "CEIL({$tt_duration_expr} / {$rounding_seconds}) * {$rounding_seconds}";
        } else {
            $tt_rounded_duration = $tt_duration_expr;
        }

        // Build rate expression matching get_summary() and invoice builder logic
        $default_rate = floatval(get_option('fs_default_hourly_rate', 75));
        $tt_rate_expression = "COALESCE(NULLIF(t.hourly_rate, 0), {$default_rate})";

        $tasks_table = $wpdb->prefix . 'fs_tasks';

        $sql = "SELECT 
                    $select_extra,
                    COUNT(*) as entry_count,
                    SUM(t.duration) as total_seconds,
                    SUM(CASE WHEN t.billable = 1 THEN t.duration ELSE 0 END) as billable_seconds,
                    SUM(CASE WHEN t.billable = 1 THEN ROUND({$tt_rounded_duration} / 3600.0, 2) * {$tt_rate_expression} ELSE 0 END) as billable_amount,
                    SUM(CASE WHEN t.invoiced = 1 THEN t.duration ELSE 0 END) as invoiced_seconds
                FROM $time_table t
                LEFT JOIN $projects_table p ON t.project_id = p.id
                LEFT JOIN $clients_table c ON p.client_id = c.id
                LEFT JOIN $tasks_table tk ON t.task_id = tk.id
                WHERE $where_clause
                GROUP BY $group_by
                ORDER BY total_seconds DESC";

        if (!empty($values)) {
            $sql = $wpdb->prepare($sql, $values); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
        }

        return $wpdb->get_results($sql); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
    }
}
