<?php
/**
 * MTC - Camera Admin Handlers
 * Form processing, CRUD routing, settings actions.
 *
 * Extracted from cameras-actions.php trait.
 *
 * @package My Trail Camera
 * @since 8.2.0
 */

if (!defined('ABSPATH')) exit;

class Mtcam_Camera_Admin_Handlers {

    /** @var My_Trail_Camera Main plugin instance. */
    private $tracker;

    /** @var Mtcam_Import_Export_Service */
    private $import_export;

    public function __construct($tracker, $import_export) {
        $this->tracker = $tracker;
        $this->import_export = $import_export;
    }

    /**
     * Trail Camera field configuration
     */
    private function get_camera_field_config() {
        return [
            'text' => [
                'name', 'location', 'gps_lat', 'gps_lon', 'manufacturer', 'profile',
                'imei', 'serial_number', 'purchase_date', 'deploy_date', 'deploy_time', 'rec_mode', 'rec_resolution', 'power_type', 'planned_days',
                'terrain_type', 'battery_preset'
            ],
            'checkbox' => [
                'police_reported',
                'bait_html', 'bait_tel',
                'sec_box', 'sec_cable', 'sec_padlock', 'sec_password', 'sec_camera',
                'gps_airtag', 'gps_tile', 'gps_samsung', 'gps_other',
                'acc_battery', 'acc_sdcard', 'acc_sim',
                'solar_blocked'
            ],
            'number' => [
                'price', 'acc_battery_price', 'acc_sdcard_price', 'acc_sim_price',
                // Prices for items shown in the merged Price & Accessories column.
                // (bait_html / bait_tel intentionally priceless — they are digital trap templates.)
                'sec_box_price', 'sec_cable_price', 'sec_padlock_price', 'sec_password_price', 'sec_camera_price',
                'gps_airtag_price', 'gps_tile_price', 'gps_samsung_price', 'gps_other_price',
                'rec_length', 'rec_day_count', 'rec_night_count', 'battery_pct',
                'solar_panel_w', 'cell_count',
            ]
        ];
    }

    /**
     * Dynamic form field processing. Used by both edit and add flows:
     *   - edit: pass cam_id (empty suffix when null/empty — keys become prefix.field_camid)
     *   - add:  pass '' for cam_id (no suffix — keys become prefix.field)
     */
    private function process_camera_fields($cam_id, $prefix = 'edit_cam_') {
        check_admin_referer( 'mtcam_settings' );

        $config = $this->get_camera_field_config();
        $data   = [];
        $suffix = ( $cam_id !== '' && $cam_id !== null ) ? '_' . $cam_id : '';

        // Text fields — only written when the form actually submitted the key.
        foreach ($config['text'] as $field) {
            $key = $prefix . $field . $suffix;
            if (isset($_POST[$key])) {
                $data[$field] = sanitize_text_field( wp_unslash( $_POST[$key] ) );
            }
        }

        // Checkboxes — unchecked checkboxes are not sent at all, so isset() is the presence test.
        foreach ($config['checkbox'] as $field) {
            $key = $prefix . $field . $suffix;
            $data[$field] = isset($_POST[$key]) ? 'yes' : 'no';
        }

        // Numeric fields — only written when the form actually submitted the key.
        foreach ($config['number'] as $field) {
            $key = $prefix . $field . $suffix;
            if (isset($_POST[$key])) {
                $data[$field] = floatval( sanitize_text_field( wp_unslash( $_POST[$key] ) ) );
            }
        }

        return $data;
    }

    /**
     * Handle all POST actions on admin_init (before any HTML output).
     * Allows wp_safe_redirect() to work without "headers already sent" errors.
     */
    public function handle_camera_actions() {
        $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
        $our_pages = array('mtcam-dashboard', 'mtcam-add-camera', 'mtcam-settings');
        if (!in_array($page, $our_pages, true)) return;

        // GET-based actions (orphan cleanup) — have their own nonce checks
        if ($page === 'mtcam-settings' && isset($_GET['mtcam_cleanup_orphans'])) {
            check_admin_referer('mtcam_cleanup_orphans');
            $existing_ids = array_keys(mtcam_get_cameras());
            mtcam_cleanup_orphaned_records($existing_ids);
            wp_safe_redirect( admin_url( 'admin.php?page=mtcam-settings&tab=maintenance&orphans_cleaned=1&_wpnonce=' . wp_create_nonce( 'mtcam_settings_notice' ) ) );
            exit;
        }

        // POST-based actions — delete and bait have their own nonce checks in handlers
        $mtcam_post_action = isset($_POST['action']) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : '';
        $mtcam_has_own_nonce = in_array($mtcam_post_action, array('delete_custom', 'generate_bait'), true)
            || isset( $_POST['mtcam_end_monitoring'] )
            || isset( $_POST['mtcam_camera_check'] );

        if (!$mtcam_has_own_nonce) {
            if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'mtcam_settings' ) ) {
                return;
            }
        }

        // Camera CRUD (shared across dashboard, add-camera, settings)
        $this->process_camera_actions();

        // Settings-specific actions (import, profiles, main save)
        if ($page === 'mtcam-settings') {
            $this->process_settings_actions();
        }
    }

    /**
     * Route camera actions to specific handlers.
     */
    private function process_camera_actions() {
        $cameras_data = mtcam_get_cameras();

        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_delete_camera().
        if ( isset( $_POST['action'] ) && 'delete_custom' === sanitize_text_field( wp_unslash( $_POST['action'] ) ) && isset( $_POST['cam_id'] ) ) {
            $this->handle_delete_camera($cameras_data);
            return;
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_add_camera().
        if ( isset( $_POST['add_camera'] ) ) {
            $this->handle_add_camera($cameras_data);
            return;
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_end_monitoring().
        if ( isset( $_POST['mtcam_end_monitoring'] ) && ! empty( $_POST['mtcam_end_monitoring'] ) ) {
            $this->handle_end_monitoring($cameras_data);
            return;
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_camera_check().
        if ( isset( $_POST['mtcam_camera_check'] ) && ! empty( $_POST['mtcam_camera_check'] ) ) {
            $this->handle_camera_check($cameras_data);
            return;
        }

        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified in handle_edit_camera().
        if ( isset( $_POST['edit_cam_id'] ) && is_array( $_POST['edit_cam_id'] ) ) {
            $this->handle_edit_camera($cameras_data);
            return;
        }
    }

    /**
     * Delete a camera.
     */
    private function handle_delete_camera($cameras_data) {
        if (!current_user_can('manage_options')) wp_die(esc_html__('Insufficient permissions.', 'my-trail-camera'), '', 403);
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce action includes cam_id, verified on the next line.
        $del_cam_id = isset( $_POST['cam_id'] ) ? sanitize_text_field( wp_unslash( $_POST['cam_id'] ) ) : '';
        check_admin_referer('delete_custom_camera_' . $del_cam_id);
        if (isset($cameras_data[$del_cam_id])) {
            mtcam_delete_camera($del_cam_id);

            $redirect_page = isset($_POST['from']) && sanitize_text_field( wp_unslash( $_POST['from'] ) ) === 'dashboard'
                ? 'mtcam-dashboard'
                : 'mtcam-settings&tab=cameras';

            wp_safe_redirect( admin_url( 'admin.php?page=' . $redirect_page . '&camera_deleted=1&_wpnonce=' . wp_create_nonce( 'mtcam_dashboard_notice' ) ) );
            exit;
        }
    }

    /**
     * Add a new camera.
     */
    private function handle_add_camera($cameras_data) {
        if ( ! current_user_can( 'manage_options' ) ) wp_die( esc_html__( 'Insufficient permissions.', 'my-trail-camera' ), '', 403 );
        check_admin_referer('mtcam_settings');

        // VALIDATION: Check required fields
        if (empty($_POST['new_cam_id'])) {
            $this->tracker->admin_notice = array('type' => 'error', 'message' => '❌ <strong>Device ID</strong> ' . esc_html__('is a required field!', 'my-trail-camera'));
            return;
        }

        if (empty($_POST['new_cam_location'])) {
            $this->tracker->admin_notice = array('type' => 'error', 'message' => '❌ <strong>' . esc_html__('Location', 'my-trail-camera') . '</strong> ' . esc_html__('is a required field!', 'my-trail-camera'));
            return;
        }

        $new_id = strtoupper( sanitize_text_field( wp_unslash( $_POST['new_cam_id'] ) ) );
        $owner_type = sanitize_text_field( wp_unslash( $_POST['new_cam_owner_type'] ?? 'me' ) );

        // Check for duplicate ID
        if (mtcam_camera_exists($new_id)) {
            $this->tracker->admin_notice = array('type' => 'error', 'message' => esc_html__('Camera with ID', 'my-trail-camera') . ' <strong>' . esc_html($new_id) . '</strong> ' . esc_html__('already exists! Choose a different ID.', 'my-trail-camera'));
            return;
        }

        // All form fields handled uniformly via the shared config-driven helper.
        // For the add flow we pass an empty cam_id so keys become `new_cam_<field>`.
        $cameras_data[$new_id] = $this->process_camera_fields( '', 'new_cam_' );

        // Add-only fields not part of the edit-form config:
        $cameras_data[$new_id]['color']           = MTCAM_DEFAULT_COLOR;
        $cameras_data[$new_id]['active']          = sanitize_text_field( wp_unslash( $_POST['new_cam_active'] ?? 'no' ) ) === 'yes' ? 'yes' : 'no';
        $cameras_data[$new_id]['tested']          = 'no';
        $cameras_data[$new_id]['stolen_date']     = '';
        $cameras_data[$new_id]['police_reported'] = 'no';
        $cameras_data[$new_id]['owner']           = $owner_type;

        // "Other" owner fields are not part of config (only visible on add form when managing friends' cameras).
        if ($owner_type !== 'me') {
            $cameras_data[$new_id]['owner_name']  = sanitize_text_field( wp_unslash( $_POST['new_cam_owner_name'] ?? '' ) );
            $cameras_data[$new_id]['owner_email'] = sanitize_email( wp_unslash( $_POST['new_cam_owner_email'] ?? '' ) );
        }

        // Save admin fingerprint for all cameras (used to detect owner testing bait files)
        $cameras_data[$new_id]['owner_fingerprint'] = array(
            'ip' => sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ?? '' ) ),
            'user_agent' => sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ),
            'created_at' => time()
        );

        // Auto-fill manufacturer from profile
        $new_profile = $cameras_data[$new_id]['profile'] ?? 'custom';
        if ($new_profile !== 'custom' && function_exists('mtcam_get_camera_profile')) {
            $prof = mtcam_get_camera_profile($new_profile);
            $cameras_data[$new_id]['manufacturer'] = $prof['manufacturer'] ?? '';
        }

        mtcam_save_camera($new_id, $cameras_data[$new_id]);

        $extra_params = '';

        // Always redirect to dashboard after adding
        wp_safe_redirect( admin_url( 'admin.php?page=mtcam-dashboard&camera_added=' . $new_id . $extra_params . '&_wpnonce=' . wp_create_nonce( 'mtcam_dashboard_notice' ) ) );
        exit;
    }

    /**
     * End monitoring — save location review and update camera.
     */
    private function handle_end_monitoring($cameras_data) {
        if ( ! current_user_can( 'manage_options' ) ) wp_die( esc_html__( 'Insufficient permissions.', 'my-trail-camera' ), '', 403 );
        check_admin_referer('mtcam_end_monitoring');
        $em_cam_id = isset( $_POST['mtcam_end_monitoring'] ) ? sanitize_text_field( wp_unslash( $_POST['mtcam_end_monitoring'] ) ) : '';

        if (!isset($cameras_data[$em_cam_id]) || !function_exists('mtcam_location_review_save')) {
            return;
        }

        $cam = $cameras_data[$em_cam_id];
        $start = $cam['deploy_date'] ?? '';
        $end = current_time('Y-m-d');
        $days = 0;
        if (!empty($start)) {
            $days = max(1, intval((strtotime($end) - strtotime($start)) / 86400));
        }

        $review_data = array(
            'cam_id'             => $em_cam_id,
            'location_name'      => sanitize_text_field( wp_unslash( $_POST['em_location'] ?? $cam['location'] ) ),
            'gps_lat'            => sanitize_text_field( wp_unslash( $_POST['em_gps_lat'] ?? $cam['gps_lat'] ) ),
            'gps_lon'            => sanitize_text_field( wp_unslash( $_POST['em_gps_lon'] ?? $cam['gps_lon'] ) ),
            'start_date'         => $start ?: $end,
            'end_date'           => $end,
            'days_count'         => $days,
            'total_videos'       => intval( wp_unslash( $_POST['em_total_videos'] ?? 0 ) ),
            'interesting_videos' => intval( wp_unslash( $_POST['em_interesting_videos'] ?? 0 ) ),
            'people_count'       => intval( wp_unslash( $_POST['em_people_count'] ?? 0 ) ),
            'satisfaction'        => intval( wp_unslash( $_POST['em_satisfaction'] ?? 3 ) ),
            'notes'              => sanitize_textarea_field( wp_unslash( $_POST['em_notes'] ?? '' ) ),
            'profile'            => sanitize_text_field( wp_unslash( $_POST['em_profile'] ?? '' ) ),
        );

        $review_id = mtcam_location_review_save( $review_data );

        // Set trail camera as at home — reset deployment fields
        $cameras_data[$em_cam_id]['active'] = 'no';
        $cameras_data[$em_cam_id]['tested'] = 'no';
        mtcam_reset_deployment_fields( $cameras_data[$em_cam_id] );
        mtcam_save_camera($em_cam_id, $cameras_data[$em_cam_id]);

        // Timeline
        $score_data = mtcam_calculate_location_score(array(
            'days_count' => $days,
            'total_videos' => intval( wp_unslash( $_POST['em_total_videos'] ?? 0 ) ),
            'interesting_videos' => intval( wp_unslash( $_POST['em_interesting_videos'] ?? 0 ) ),
            'people_count' => intval( wp_unslash( $_POST['em_people_count'] ?? 0 ) ),
            'satisfaction' => intval( wp_unslash( $_POST['em_satisfaction'] ?? 3 ) ),
        ));

        wp_safe_redirect( wp_nonce_url( admin_url('admin.php?page=mtcam-locations&saved=1'), 'mtcam_settings_notice' ) );
        exit;
    }

    /**
     * Record a camera check (SD card swap, battery replacement, etc.).
     */
    private function handle_camera_check($cameras_data) {
        if ( ! current_user_can( 'manage_options' ) ) wp_die( esc_html__( 'Insufficient permissions.', 'my-trail-camera' ), '', 403 );
        check_admin_referer('mtcam_settings');
        $check_cam_id = isset( $_POST['mtcam_camera_check'] ) ? sanitize_text_field( wp_unslash( $_POST['mtcam_camera_check'] ) ) : '';

        $redirect = sanitize_text_field( wp_unslash( $_POST['redirect_to'] ?? 'dashboard' ) );
        $page     = ( $redirect === 'dashboard' ) ? 'mtcam-dashboard' : 'mtcam-settings';

        if ( ! isset( $cameras_data[ $check_cam_id ] ) ) {
            wp_safe_redirect( admin_url( 'admin.php?page=' . $page . '&camera_check_error=' . urlencode( $check_cam_id ) . '&_wpnonce=' . wp_create_nonce( 'mtcam_dashboard_notice' ) ) );
            exit;
        }

        // Store last check date on the camera record
        $cameras_data[$check_cam_id]['last_checked'] = wp_date('Y-m-d');
        mtcam_save_camera($check_cam_id, $cameras_data[$check_cam_id]);

        wp_safe_redirect( admin_url( 'admin.php?page=' . $page . '&camera_checked=' . urlencode( $check_cam_id ) . '&_wpnonce=' . wp_create_nonce( 'mtcam_dashboard_notice' ) ) );
        exit;
    }

    /**
     * Edit one or more cameras — update fields, track changes.
     */
    private function handle_edit_camera($cameras_data) {
        if ( ! current_user_can( 'manage_options' ) ) wp_die( esc_html__( 'Insufficient permissions.', 'my-trail-camera' ), '', 403 );
        check_admin_referer('mtcam_settings');

        $edit_cam_ids = isset( $_POST['edit_cam_id'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['edit_cam_id'] ) ) : array();
        $mtcam_old_cameras = $cameras_data; // Snapshot for GPS change detection.
        foreach ($edit_cam_ids as $cam_id) {
            if (isset($cameras_data[$cam_id])) {
                $is_my = mtcam_is_my_camera($cameras_data[$cam_id]);
                $old_cam = $cameras_data[$cam_id]; // Snapshot for comparison

                // Keep owner_fingerprint if it exists
                $owner_fingerprint = $cameras_data[$cam_id]['owner_fingerprint'] ?? null;

                // Handle radio status (active / tested / stolen / at home)
                $cam_status = sanitize_text_field( wp_unslash( $_POST['edit_cam_status_' . $cam_id] ?? 'active' ) );
                $stolen_date = '';
                $active = 'no';
                $tested = 'no';

                if ($cam_status === 'active') {
                    $active = 'yes';
                } elseif ($cam_status === 'tested') {
                    $tested = 'yes';
                    $active = 'yes';
                } elseif ($cam_status === 'stolen') {
                    if (!empty($_POST['edit_cam_stolen_date_' . $cam_id])) {
                        $stolen_date = sanitize_text_field( wp_unslash( $_POST['edit_cam_stolen_date_' . $cam_id] ) );
                    } else {
                        $stolen_date = wp_date('Y-m-d');
                    }
                }
                // at home = active:no, tested:no, stolen_date:empty

                // Dynamic field processing
                $processed_data = $this->process_camera_fields($cam_id, 'edit_cam_');

                $cameras_data[$cam_id] = array_merge(
                    $cameras_data[$cam_id],
                    $processed_data,
                    [
                        'color' => MTCAM_DEFAULT_COLOR,
                        'active' => $active,
                        'tested' => $tested,
                        'stolen_date' => $stolen_date,
                        'owner' => $cameras_data[$cam_id]['owner'] ?? 'me',
                        'owner_name' => $cameras_data[$cam_id]['owner_name'] ?? '',
                        'owner_email' => $cameras_data[$cam_id]['owner_email'] ?? '',
                        'owner_fingerprint' => $owner_fingerprint
                    ]
                );

                // Reset deployment fields when trail camera goes home (was active/tested, now at home)
                if (($old_cam['active'] ?? 'no') === 'yes' && $cam_status === 'home') {
                    mtcam_reset_deployment_fields( $cameras_data[$cam_id] );
                }

                // Auto-fill manufacturer from profile
                $profile_id = $cameras_data[$cam_id]['profile'] ?? 'custom';
                if ($profile_id !== 'custom' && function_exists('mtcam_get_camera_profile')) {
                    $profile = mtcam_get_camera_profile($profile_id);
                    $cameras_data[$cam_id]['manufacturer'] = $profile['manufacturer'] ?? '';
                }

                // Tested cameras should not have recovered_date
                if (mtcam_is_tested($cameras_data[$cam_id]) && !empty($cameras_data[$cam_id]['recovered_date'])) {
                    $cameras_data[$cam_id]['recovered_date'] = '';
                }

                $this->track_camera_changes($cam_id, $old_cam, $cameras_data[$cam_id]);

                // v8.0: Saves only one camera, not the entire array
                mtcam_save_camera($cam_id, $cameras_data[$cam_id]);
            }
        }

        // Settlement proximity risk check — run if GPS changed on the last edited camera.
        $extra_params = '';

        // Redirect back to where the form was submitted from
        if (isset($_POST['redirect_to'])) {
            $redirect_to = sanitize_text_field( wp_unslash( $_POST['redirect_to'] ) );
            if ($redirect_to === 'dashboard') {
                $redirect_page = 'mtcam-dashboard';
            } elseif ($redirect_to === 'add-camera') {
                $redirect_page = 'mtcam-add-camera';
            } else {
                $redirect_page = 'mtcam-settings&tab=cameras';
            }
        } else {
            $redirect_page = 'mtcam-settings&tab=cameras';
        }

        wp_safe_redirect( admin_url( 'admin.php?page=' . $redirect_page . '&camera_updated=1' . $extra_params . '&_wpnonce=' . wp_create_nonce( 'mtcam_dashboard_notice' ) ) );
        exit;
    }

    /**
     * Compare old and new camera data, log differences.
     *
     * @param string $cam_id Camera ID.
     * @param array  $old    Camera data before edit.
     * @param array  $new    Camera data after edit (may be modified — recovered_date added).
     */
    private function track_camera_changes($cam_id, $old, &$new) {
        // Set recovered_date when unmarking stolen (BASIC + PRO behaviour).
        if (empty($new['stolen_date']) && !empty($old['stolen_date'])) {
            if (mtcam_is_tested($new)) {
                $new['recovered_date'] = '';
            } else {
                $new['recovered_date'] = wp_date('Y-m-d');
            }
        }

    }

    /**
     * Settings POST actions that require redirect (called from admin_init).
     */
    private function process_settings_actions() {
        if ( ! current_user_can( 'manage_options' ) ) return;

        // Import backup — delegated to import/export service
        $this->import_export->process_import();

        // Main settings save
        if (isset($_POST['mtcam_settings_submit'])) {
            check_admin_referer('mtcam_settings');

            update_option('mtcam_notifications', sanitize_text_field( wp_unslash( $_POST['notifications'] ?? '' ) ));
            update_option('mtcam_notify_email', sanitize_textarea_field( wp_unslash( $_POST['notify_email'] ?? '' ) ));
            update_option('mtcam_show_ip', isset($_POST['show_ip']) ? 'yes' : 'no');
            update_option('mtcam_show_photo', isset($_POST['show_photo']) ? 'yes' : 'no');

            // Public widget checkbox settings (stolen + active)
            $widget_fields = array( 'name', 'manufacturer', 'imei', 'location', 'gps', 'dates', 'baits', 'security', 'gps_trackers', 'photo' );
            foreach ( array( 'stolen', 'active' ) as $type ) {
                foreach ( $widget_fields as $field ) {
                    $key = "public_{$type}_show_{$field}";
                    update_option( "mtcam_{$key}", isset( $_POST[ $key ] ) ? 'yes' : 'no' );
                }
            }
            update_option( 'mtcam_public_stolen_show_police', isset( $_POST['public_stolen_show_police'] ) ? 'yes' : 'no' );

            $valid_ip_sources = array( 'remote_addr', 'cf_connecting_ip', 'x_forwarded_for' );
            $ip_source = sanitize_text_field( wp_unslash( $_POST['ip_source'] ?? 'remote_addr' ) );
            update_option( 'mtcam_ip_source', in_array( $ip_source, $valid_ip_sources, true ) ? $ip_source : 'remote_addr' );

            update_option('mtcam_show_battery_stolen', isset($_POST['show_battery_stolen']) ? 'yes' : 'no');

            wp_safe_redirect( admin_url( 'admin.php?page=mtcam-settings&settings_saved=1&_wpnonce=' . wp_create_nonce( 'mtcam_settings_notice' ) ) );
            exit;
        }
    }
}
