<?php
/**
 * Projects Controller
 *
 * @package Freelance_Studio
 */

class FS_Projects_Controller {

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

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $this->handle_post();
            return;
        }

        switch ($action) {
            case 'add':
                $this->add();
                break;
            case 'edit':
                $this->edit($id);
                break;
            case 'view':
                $this->view($id);
                break;
            case 'invoice_deposit':
                $this->invoice_deposit($id);
                break;
            default:
                $this->index();
                break;
        }
    }

    /**
     * Handle POST requests
     */
    private function handle_post() {
        if (!isset($_POST['fs_project_nonce']) || !wp_verify_nonce($_POST['fs_project_nonce'], 'fs_save_project')) {
            ob_end_clean();
            wp_die(esc_html__('Security check failed', 'freelance-studio'));
        }

        $action = isset($_POST['action']) ? sanitize_text_field(wp_unslash($_POST['action'])) : '';
        $id = isset($_POST['project_id']) ? intval($_POST['project_id']) : 0;

        // Process services
        $services = array();
        if (!empty($_POST['services']) && is_array($_POST['services'])) {
            foreach ($_POST['services'] as $idx => $svc) {
                if (!empty($svc['name'])) {
                    $service_data = array(
                        'name' => sanitize_text_field($svc['name']),
                        'description' => sanitize_textarea_field($svc['description'] ?? ''),
                        'pricing_type' => sanitize_text_field($svc['pricing_type'] ?? 'fixed'),
                        'hourly_source' => sanitize_text_field($svc['hourly_source'] ?? 'estimated'),
                        'activity' => sanitize_text_field($svc['activity'] ?? ''),
                        'rate' => floatval($svc['rate'] ?? 0),
                        'quantity' => floatval($svc['quantity'] ?? 1),
                        'amount' => floatval($svc['amount'] ?? 0),
                    );
                    
                    // v3.9.0: Include retainer-specific fields if pricing type is retainer
                    if ($service_data['pricing_type'] === 'retainer') {
                        $service_data['retainer_amount'] = floatval($svc['retainer_amount'] ?? 0);
                        $service_data['retainer_hours'] = floatval($svc['retainer_hours'] ?? 0);
                        $service_data['retainer_rollover'] = isset($svc['retainer_rollover']) ? 1 : 0;
                        $service_data['retainer_overage_rate'] = floatval($svc['retainer_overage_rate'] ?? 0);
                    }
                    
                    // v7.9.0: Include hour cap fields for hourly tracked services
                    if ($service_data['pricing_type'] === 'hourly' && $service_data['hourly_source'] === 'tracked') {
                        $cap_enabled = !empty($svc['hour_cap_enabled']);
                        $service_data['hour_cap'] = $cap_enabled ? floatval($svc['hour_cap'] ?? 0) : 0;
                        $service_data['hour_cap_overage_rate'] = $cap_enabled ? floatval($svc['hour_cap_overage_rate'] ?? 0) : 0;
                        $service_data['hour_cap_notify_client'] = $cap_enabled && !empty($svc['hour_cap_notify_client']) ? 1 : 0;
                        $service_data['hour_cap_notify_contact_id'] = $cap_enabled && !empty($svc['hour_cap_notify_contact_id']) ? sanitize_text_field($svc['hour_cap_notify_contact_id']) : 'primary';
                    }
                    
                    $services[] = $service_data;
                }
            }
        }

        // Handle deposit settings
        $deposit_required = isset($_POST['deposit_required']) && $_POST['deposit_required'];
        $deposit_type = sanitize_text_field(wp_unslash($_POST['deposit_type'] ?? 'percentage'));
        $deposit_percentage = 0;
        $deposit_amount = 0;
        
        if ($deposit_required) {
            if ($deposit_type === 'percentage') {
                $deposit_percentage = floatval($_POST['deposit_percentage'] ?? 0);
                // Calculate amount from percentage
                $total = floatval($_POST['fixed_price'] ?? 0);
                $deposit_amount = $total * ($deposit_percentage / 100);
            } else {
                $deposit_amount = floatval($_POST['deposit_fixed_amount'] ?? 0);
            }
        }

        // v3.9.0: Extract retainer settings from services for backwards compatibility
        $is_retainer = 0;
        $retainer_amount = null;
        $retainer_hours = null;
        $retainer_rollover = 1;
        
        if (!empty($services)) {
            foreach ($services as $service) {
                if (isset($service['pricing_type']) && $service['pricing_type'] === 'retainer') {
                    $is_retainer = 1;
                    $retainer_amount = isset($service['retainer_amount']) ? floatval($service['retainer_amount']) : null;
                    $retainer_hours = isset($service['retainer_hours']) ? floatval($service['retainer_hours']) : null;
                    $retainer_rollover = isset($service['retainer_rollover']) ? 1 : 0;
                    break; // Use first retainer service found
                }
            }
        }

        // Retainer reset day (project-level, shared across all retainer services)
        $retainer_reset_day = null;
        if (!empty($_POST['retainer_reset_day'])) {
            $raw_day = intval($_POST['retainer_reset_day']);
            if ($raw_day >= 1 && $raw_day <= 28) {
                $retainer_reset_day = $raw_day;
            }
        }

        $data = array(
            'client_id' => intval($_POST['client_id']),
            'name' => sanitize_text_field(wp_unslash($_POST['name'])),
            'description' => sanitize_textarea_field(wp_unslash($_POST['description'])),
            'status' => sanitize_text_field(wp_unslash($_POST['status'])),
            'billing_type' => sanitize_text_field(wp_unslash($_POST['billing_type'])),
            'estimated_hours' => isset($_POST['estimated_hours']) ? floatval($_POST['estimated_hours']) : null,
            'fixed_price' => isset($_POST['fixed_price']) ? floatval($_POST['fixed_price']) : null,
            'budget' => isset($_POST['budget']) ? floatval($_POST['budget']) : null,
            'deposit_type' => $deposit_type,
            'deposit_percentage' => $deposit_percentage,
            'deposit_amount' => $deposit_amount,
            'start_date' => !empty($_POST['start_date']) ? sanitize_text_field(wp_unslash($_POST['start_date'])) : null,
            'due_date' => !empty($_POST['due_date']) ? sanitize_text_field(wp_unslash($_POST['due_date'])) : null,
            'is_retainer' => $is_retainer,
            'retainer_amount' => $retainer_amount,
            'retainer_hours' => $retainer_hours,
            'retainer_rollover' => $retainer_rollover,
            'retainer_reset_day' => $retainer_reset_day,
            'notes' => sanitize_textarea_field(wp_unslash($_POST['notes'])),
            'services' => $services,
            'billing_frequency' => sanitize_text_field(wp_unslash($_POST['billing_frequency'] ?? 'once')),
            'first_invoice_date' => !empty($_POST['first_invoice_date']) ? sanitize_text_field(wp_unslash($_POST['first_invoice_date'])) : null,
        );

        // Clean buffer before redirect
        ob_end_clean();
        
        if ($action === 'update' && $id) {
            $result = FS_Project::update($id, $data);
            $message = $result !== false ? 'updated' : 'error';
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&action=edit&id=' . $id . '&message=' . $message));
        } else {
            // Check free plan project-per-client limit before creating
            if ( function_exists( 'fs_studio_limit_reached' ) && fs_studio_limit_reached( 'projects_per_client', array( 'client_id' => $data['client_id'] ) ) ) {
                FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&message=limit_reached'));
                exit;
            }
            
            $project_id = FS_Project::create($data);
            if ($project_id) {
                FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&action=edit&id=' . $project_id . '&message=created'));
            } else {
                FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&action=add&message=error'));
            }
        }
        exit;
    }

    /**
     * List all projects
     */
    public function index() {
        // Handle archive/unarchive actions
        if (isset($_GET['do_archive']) && isset($_GET['id']) && wp_verify_nonce($_GET['_wpnonce'] ?? '', 'fs_archive_project')) {
            $project_id = intval($_GET['id']);
            FS_Project::archive($project_id);
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&message=archived'));
        }
        if (isset($_GET['do_unarchive']) && isset($_GET['id']) && wp_verify_nonce($_GET['_wpnonce'] ?? '', 'fs_unarchive_project')) {
            $project_id = intval($_GET['id']);
            FS_Project::unarchive($project_id);
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&tab=archived&message=unarchived'));
        }
        
        $status_filter = isset($_GET['status']) ? sanitize_text_field($_GET['status']) : null;
        $client_filter = isset($_GET['client_id']) ? intval($_GET['client_id']) : null;
        $billing_filter = isset($_GET['billing_type']) ? sanitize_text_field($_GET['billing_type']) : null;
        $orderby = isset($_GET['orderby']) ? sanitize_text_field($_GET['orderby']) : 'start_date';
        $order = isset($_GET['order']) ? sanitize_text_field($_GET['order']) : 'DESC';
        $tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'active';
        
        // Pagination
        $per_page = isset($_GET['per_page']) ? intval($_GET['per_page']) : 25;
        $per_page = in_array($per_page, array(10, 25, 50, 100)) ? $per_page : 25;
        $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1;
        $offset = ($current_page - 1) * $per_page;
        
        $args = array(
            'orderby' => $orderby,
            'order' => $order,
            'limit' => $per_page,
            'offset' => $offset,
        );
        if ($status_filter) {
            $args['status'] = $status_filter;
        }
        if ($client_filter) {
            $args['client_id'] = $client_filter;
        }
        if ($billing_filter) {
            $args['billing_type'] = $billing_filter;
        }
        
        // Handle archived tab
        if ($tab === 'archived') {
            $args['archived'] = true;
        } else {
            $args['archived'] = false;
        }
        
        $projects = FS_Project::get_all($args);
        $clients = FS_Client::get_for_dropdown();
        $statuses = FS_Project::get_statuses();
        $message = isset($_GET['message']) ? sanitize_text_field($_GET['message']) : '';
        
        // Get counts for tabs
        $active_count = FS_Project::get_count(false);
        $archived_count = FS_Project::get_count(true);
        
        // Pagination count — use same filters minus limit/offset
        $count_args = $args;
        unset($count_args['limit'], $count_args['offset'], $count_args['orderby'], $count_args['order']);
        $total_items = FS_Project::count($count_args);
        $total_pages = ceil($total_items / $per_page);
        
        include JEEB_FS_PLUGIN_DIR . 'includes/views/projects/list.php';
    }

    /**
     * Add new project form
     */
    public function add() {
        $project = null;
        $clients = FS_Client::get_for_dropdown();
        $statuses = FS_Project::get_statuses();
        $billing_types = FS_Project::get_billing_types();
        $default_hourly_rate = get_option('fs_default_hourly_rate', 75);
        $default_deposit = get_option('fs_default_deposit_percentage', 50);
        $is_new = true;
        $message = isset($_GET['message']) ? sanitize_text_field($_GET['message']) : '';
        
        // Pre-select client if passed in URL
        $selected_client_id = isset($_GET['client_id']) ? intval($_GET['client_id']) : 0;
        
        // Pre-fill from contract
        $prefill = array();
        $source_contract_id = isset($_GET['contract_id']) ? intval($_GET['contract_id']) : 0;
        $source_proposal_id = isset($_GET['proposal_id']) ? intval($_GET['proposal_id']) : 0;
        
        if ($source_contract_id) {
            $source_contract = FS_Contract::get($source_contract_id);
            if ($source_contract) {
                $selected_client_id = $source_contract->client_id;
                $prefill['name'] = $source_contract->title;
                $prefill['contract_id'] = $source_contract_id;
                
                // Pass services directly
                $contract_services = is_array($source_contract->services) ? $source_contract->services : (json_decode($source_contract->services, true) ?: array());
                if (!empty($contract_services)) {
                    // Map contract service fields to project service format
                    $prefill['services'] = array();
                    foreach ($contract_services as $svc) {
                        $prefill['services'][] = array(
                            'name'         => $svc['name'] ?? '',
                            'description'  => $svc['description'] ?? '',
                            'pricing_type' => $svc['pricing_type'] ?? 'fixed',
                            'rate'         => $svc['rate'] ?? '',
                            'quantity'     => $svc['quantity'] ?? 1,
                            'amount'       => $svc['total'] ?? $svc['amount'] ?? '',
                        );
                    }
                }
                $prefill['billing_type'] = 'fixed';
                
                // Dates
                if (!empty($source_contract->start_date) && strtotime($source_contract->start_date) > 0) {
                    $prefill['start_date'] = $source_contract->start_date;
                }
                if (!empty($source_contract->end_date) && strtotime($source_contract->end_date) > 0) {
                    $prefill['due_date'] = $source_contract->end_date;
                }
                
                // Deposit
                if (!empty($source_contract->deposit_type) && !empty($source_contract->deposit_value)) {
                    $prefill['deposit_type'] = $source_contract->deposit_type;
                    $prefill['deposit_value'] = $source_contract->deposit_value;
                }
                
                // Notes
                if (!empty($source_contract->notes)) {
                    $prefill['description'] = $source_contract->notes;
                }
            }
        } elseif ($source_proposal_id) {
            $source_proposal = FS_Proposal::get($source_proposal_id);
            if ($source_proposal) {
                $selected_client_id = $source_proposal->client_id;
                $prefill['name'] = $source_proposal->title;
                $prefill['proposal_id'] = $source_proposal_id;
                
                // Budget from total
                if (!empty($source_proposal->total_amount) && $source_proposal->total_amount > 0) {
                    $prefill['budget'] = $source_proposal->total_amount;
                }
                $prefill['billing_type'] = 'fixed';
                
                // Pass services directly
                $proposal_services = is_array($source_proposal->services) ? $source_proposal->services : (json_decode($source_proposal->services, true) ?: array());
                if (!empty($proposal_services)) {
                    $prefill['services'] = array();
                    foreach ($proposal_services as $svc) {
                        $prefill['services'][] = array(
                            'name'         => $svc['name'] ?? '',
                            'description'  => $svc['description'] ?? '',
                            'pricing_type' => $svc['pricing_type'] ?? 'fixed',
                            'rate'         => $svc['rate'] ?? '',
                            'quantity'     => $svc['quantity'] ?? 1,
                            'amount'       => $svc['total'] ?? $svc['amount'] ?? '',
                        );
                    }
                }
                
                // Deposit
                if (!empty($source_proposal->deposit_type) && !empty($source_proposal->deposit_value)) {
                    $prefill['deposit_type'] = $source_proposal->deposit_type;
                    $prefill['deposit_value'] = $source_proposal->deposit_value;
                }
                
                // Notes
                if (!empty($source_proposal->notes)) {
                    $prefill['description'] = $source_proposal->notes;
                }
            }
        }
        
        include JEEB_FS_PLUGIN_DIR . 'includes/views/projects/form.php';
    }

    /**
     * Edit project form
     */
    public function edit($id) {
        $project = FS_Project::get($id);
        
        if (!$project) {
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&message=not_found'));
            exit;
        }
        
        $clients = FS_Client::get_for_dropdown();
        $statuses = FS_Project::get_statuses();
        $billing_types = FS_Project::get_billing_types();
        $default_hourly_rate = get_option('fs_default_hourly_rate', 75);
        $default_deposit = get_option('fs_default_deposit_percentage', 50);
        $is_new = false;
        $message = isset($_GET['message']) ? sanitize_text_field($_GET['message']) : '';
        
        include JEEB_FS_PLUGIN_DIR . 'includes/views/projects/form.php';
    }

    /**
     * View project details
     */
    public function view($id) {
        $project = FS_Project::get($id);
        
        if (!$project) {
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&message=not_found'));
            exit;
        }
        
        $client = FS_Client::get($project->client_id);
        $invoices = FS_Invoice::get_all(array('project_id' => $id));
        $expenses = FS_Expense::get_all(array('project_id' => $id));
        
        // Timer-related data for the Timer tab
        $running_timer = FS_Time_Entry::get_running();
        $projects = FS_Project::get_all(array('status' => array('pending', 'active')));
        $activity_types = FS_Time_Entry::get_activity_types();
        $selected_project_id = $id;
        
        include JEEB_FS_PLUGIN_DIR . 'includes/views/projects/view.php';
    }

    /**
     * Create deposit invoice for project
     */
    public function invoice_deposit($id) {
        // Verify nonce
        if (!isset($_GET['_wpnonce']) || !wp_verify_nonce($_GET['_wpnonce'], 'fs_invoice_deposit_' . $id)) {
            wp_die(esc_html__('Security check failed', 'freelance-studio'));
        }

        $project = FS_Project::get($id);
        
        if (!$project) {
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&message=not_found'));
            exit;
        }

        // Check if deposit is required and not yet paid
        $has_deposit = ($project->deposit_amount > 0 || $project->deposit_percentage > 0);
        if (!$has_deposit || $project->deposit_paid) {
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&action=view&id=' . $id . '&message=deposit_not_required'));
            exit;
        }

        // Calculate deposit amount
        $deposit_amount = $project->deposit_amount;
        if (!$deposit_amount && $project->deposit_percentage > 0) {
            $project_total = $project->fixed_price ?: 0;
            $deposit_amount = $project_total * ($project->deposit_percentage / 100);
        }

        // Build deposit line item
        $deposit_label = __('Project Deposit', 'freelance-studio');
        if ($project->deposit_percentage > 0) {
            $deposit_label .= ' (' . $project->deposit_percentage . '%)';
        }

        $deposit_items = array(
            array(
                'description' => $deposit_label,
                'quantity' => 1,
                'rate' => $deposit_amount,
                'amount' => $deposit_amount,
            )
        );

        // Create invoice for deposit
        $invoice_data = array(
            'client_id' => $project->client_id,
            'project_id' => $project->id,
            'invoice_number' => FS_Invoice::generate_invoice_number(),
            'invoice_date' => gmdate('Y-m-d'),
            'due_date' => gmdate('Y-m-d', strtotime('+7 days')),
            'status' => 'draft',
            'subtotal' => $deposit_amount,
            'total' => $deposit_amount,
            'is_deposit' => 1,
            /* translators: 1. for project value */
            'notes' => sprintf(__('Deposit for project: %s', 'freelance-studio'), $project->name),
            'items' => $deposit_items,
        );

        $invoice_id = FS_Invoice::create($invoice_data);

        if ($invoice_id) {

            // Redirect to edit the invoice
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-finances&tab=invoices&action=edit&id=' . $invoice_id . '&message=deposit_created'));
        } else {
            FS_Admin::safe_redirect(admin_url('admin.php?page=fs-projects&action=view&id=' . $id . '&message=error'));
        }
        exit;
    }
}
