<?php

namespace PloverCRM\Modules\NativeCRM\ImportExport;

use PloverCRM\Core\AdminMenu;
use PloverCRM\Core\CRM\Providers\NativeCRMProvider;
use PloverCRM\Modules\NativeCRM\CustomFieldsManager;

/**
 * CSV Import/Export Manager
 */
class CSVManager
{
    private const BATCH_SIZE = 50;
    private const UPLOAD_DIR = 'plover-crm-imports';
    private const EXPORT_DIR = 'plover-crm-exports';

    private NativeCRMProvider $crmProvider;
    private CustomFieldsManager $customFieldsManager;

    public function __construct()
    {
        $this->crmProvider = new NativeCRMProvider();
        $this->customFieldsManager = new CustomFieldsManager();
    }

    /**
     * Register hooks
     */
    public function register(): void
    {
        // Use AdminMenu to register submenu - priority 30 to show after Contacts, Lists, Tags
        AdminMenu::addSubmenu(
            'plover-crm-import-export',
            'Import/Export',
            'Import/Export',
            [$this, 'renderPage'],
            30,
            'manage_options',
            false
        );

        add_action('wp_ajax_plover_crm_upload_csv', [$this, 'ajaxUploadCSV']);
        add_action('wp_ajax_plover_crm_process_import', [$this, 'ajaxProcessImport']);
        add_action('wp_ajax_plover_crm_cancel_import', [$this, 'ajaxCancelImport']);
        add_action('wp_ajax_plover_crm_export_csv', [$this, 'ajaxExportCSV']);


    }

    public function renderPage(): void
    {
        include __DIR__ . '/../Views/csv-import-export.php';
    }

    /**
     * AJAX: Upload and parse CSV
     */
    public function ajaxUploadCSV(): void
    {
        check_ajax_referer('plover_crm_csv', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error('Permission denied');
        }

        if (empty($_FILES['file'])) {
            wp_send_json_error('No file uploaded');
        }

        $file = $_FILES['file'];

        if ($file['error'] !== UPLOAD_ERR_OK) {
            wp_send_json_error('Upload failed');
        }

        if (strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)) !== 'csv') {
            wp_send_json_error('Only CSV files allowed');
        }

        // Save file
        $uploadDir = wp_upload_dir();
        $importDir = $uploadDir['basedir'] . '/' . self::UPLOAD_DIR;
        if (!file_exists($importDir)) {
            wp_mkdir_p($importDir);
            file_put_contents($importDir . '/.htaccess', 'deny from all');
        }

        $importId = wp_generate_uuid4();
        $filePath = $importDir . '/' . $importId . '.csv';

        if (!move_uploaded_file($file['tmp_name'], $filePath)) {
            wp_send_json_error('Failed to save file');
        }

        // Parse CSV
        $handle = fopen($filePath, 'r');
        if (!$handle) {
            wp_send_json_error('Failed to read file');
        }

        $headers = fgetcsv($handle);
        if (!$headers) {
            fclose($handle);
            unlink($filePath);
            wp_send_json_error('Invalid CSV file');
        }

        // Clean headers
        $headers = array_map(fn($h) => trim(strtolower(str_replace(['"', "'"], '', $h))), $headers);

        // Count rows and get samples
        $totalRows = 0;
        $samples = [];
        while (($row = fgetcsv($handle)) !== false) {
            $totalRows++;
            if (count($samples) < 3) {
                $samples[] = array_combine($headers, array_pad($row, count($headers), ''));
            }
        }
        fclose($handle);

        if ($totalRows === 0) {
            unlink($filePath);
            wp_send_json_error('CSV has no data rows');
        }

        // Auto-detect mapping
        $mapping = $this->autoDetectMapping($headers);

        // Save import state
        update_option('plover_crm_import_' . $importId, [
            'file_path' => $filePath,
            'headers' => $headers,
            'total' => $totalRows,
            'processed' => 0,
            'created' => 0,
            'updated' => 0,
            'skipped' => 0,
            'errors' => 0,
            'status' => 'pending',
        ]);



        wp_send_json_success([
            'import_id' => $importId,
            'headers' => $headers,
            'total' => $totalRows,
            'mapping' => $mapping,
            'samples' => $samples,
            'fields' => $this->getAvailableFields(),
        ]);
    }

    /**
     * AJAX: Process import batch
     */
    public function ajaxProcessImport(): void
    {
        check_ajax_referer('plover_crm_csv', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error('Permission denied');
        }

        $importId = sanitize_text_field($_POST['import_id'] ?? '');
        $data = get_option('plover_crm_import_' . $importId);

        if (!$data || $data['status'] === 'cancelled') {
            wp_send_json_error('Import not found or cancelled');
        }

        $mapping = isset($_POST['mapping']) ? array_map('sanitize_text_field', $_POST['mapping']) : [];
        $options = [
            'duplicate' => sanitize_text_field($_POST['duplicate'] ?? 'skip'),
            'lists' => isset($_POST['lists']) ? array_map('intval', $_POST['lists']) : [],
            'tags' => isset($_POST['tags']) ? array_map('intval', $_POST['tags']) : [],
        ];

        // Open file and skip to current position
        $handle = fopen($data['file_path'], 'r');
        fgetcsv($handle); // Skip header
        for ($i = 0; $i < $data['processed']; $i++) {
            fgetcsv($handle);
        }

        // Set flag to suppress hooks during import
        if (!defined('WPR_CRM_IMPORTING')) {
            define('WPR_CRM_IMPORTING', true);
        }

        // Process batch
        $batchCreated = 0;
        $batchUpdated = 0;
        $batchSkipped = 0;
        $batchErrors = 0;
        $processed = 0;

        while ($processed < self::BATCH_SIZE && ($row = fgetcsv($handle)) !== false) {
            $rowData = array_combine($data['headers'], array_pad($row, count($data['headers']), ''));
            $result = $this->importRow($rowData, $mapping, $options);

            if ($result === 'created') $batchCreated++;
            elseif ($result === 'updated') $batchUpdated++;
            elseif ($result === 'skipped') $batchSkipped++;
            else $batchErrors++;

            $processed++;
        }
        fclose($handle);

        // Update state
        $data['processed'] += $processed;
        $data['created'] += $batchCreated;
        $data['updated'] += $batchUpdated;
        $data['skipped'] += $batchSkipped;
        $data['errors'] += $batchErrors;

        $isComplete = $data['processed'] >= $data['total'];
        if ($isComplete) {
            $data['status'] = 'completed';
            unlink($data['file_path']);
        }

        update_option('plover_crm_import_' . $importId, $data);



        wp_send_json_success([
            'processed' => $data['processed'],
            'total' => $data['total'],
            'created' => $data['created'],
            'updated' => $data['updated'],
            'skipped' => $data['skipped'],
            'errors' => $data['errors'],
            'complete' => $isComplete,
        ]);
    }

    /**
     * Import single row
     */
    private function importRow(array $row, array $mapping, array $options): string
    {
        $contact = [];
        $customFields = [];

        foreach ($mapping as $csvCol => $field) {
            if (empty($field) || $field === '_skip') continue;

            $value = $row[$csvCol] ?? '';
            if (strpos($field, 'cf_') === 0) {
                $customFields[substr($field, 3)] = $value;
            } else {
                $contact[$field] = $value;
            }
        }

        // Check unique field
        $uniqueField = get_option('plover_crm_unique_field', 'email');
        $uniqueValue = $uniqueField === 'email' ? ($contact['email'] ?? '') : ($uniqueField === 'phone' ? ($contact['phone'] ?? '') : ($customFields[str_replace('plover_crm_cf_', '', $uniqueField)] ?? ''));

        if (empty($uniqueValue)) {
            return 'error';
        }

        // Check existing
        $existing = $this->findExisting($uniqueField, $uniqueValue);

        if ($existing) {
            if ($options['duplicate'] === 'skip') return 'skipped';
            if ($options['duplicate'] === 'update') $contact['id'] = $existing;
        }

        // Set defaults
        if (!empty($customFields)) $contact['custom_fields'] = $customFields;
        if (!empty($options['lists'])) $contact['lists'] = $options['lists'];
        if (!empty($options['tags'])) $contact['tags'] = $options['tags'];

        $result = $this->crmProvider->createOrUpdateContact($contact);

        if (!$result) return 'error';
        return $existing && isset($contact['id']) ? 'updated' : 'created';
    }

    private function findExisting(string $field, string $value): ?int
    {
        if ($field === 'email') {
            $contact = $this->crmProvider->getContactByEmail($value);
            return $contact ? $contact['id'] : null;
        }

        $metaKey = $field === 'phone' ? 'plover_crm_phone' : $field;
        $query = new \WP_Query([
            'post_type' => 'plover_crm_contact',
            'posts_per_page' => 1,
            'meta_query' => [['key' => $metaKey, 'value' => $value]]
        ]);

        return $query->have_posts() ? $query->posts[0]->ID : null;
    }

    /**
     * AJAX: Cancel import
     */
    public function ajaxCancelImport(): void
    {
        check_ajax_referer('plover_crm_csv', 'nonce');

        $importId = sanitize_text_field($_POST['import_id'] ?? '');
        $data = get_option('plover_crm_import_' . $importId);

        if ($data) {
            $data['status'] = 'cancelled';
            update_option('plover_crm_import_' . $importId, $data);
            if (file_exists($data['file_path'])) unlink($data['file_path']);
        }



        wp_send_json_success();
    }

    /**
     * AJAX: Export contacts to CSV
     */
    public function ajaxExportCSV(): void
    {
        check_ajax_referer('plover_crm_csv', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error('Permission denied');
        }

        $filters = [
            'all' => filter_var($_POST['all'] ?? true, FILTER_VALIDATE_BOOLEAN),
            'lists' => isset($_POST['lists']) ? array_map('intval', $_POST['lists']) : [],
            'tags' => isset($_POST['tags']) ? array_map('intval', $_POST['tags']) : [],
            'date_from' => sanitize_text_field($_POST['date_from'] ?? ''),
            'date_to' => sanitize_text_field($_POST['date_to'] ?? ''),
        ];
        $includeCustom = filter_var($_POST['include_custom'] ?? true, FILTER_VALIDATE_BOOLEAN);

        // Build query
        $args = [
            'post_type' => 'plover_crm_contact',
            'posts_per_page' => -1,
            'post_status' => 'publish',
        ];

        if (!$filters['all']) {
            if (!empty($filters['date_from'])) {
                $args['date_query'][] = ['after' => $filters['date_from'], 'inclusive' => true];
            }
            if (!empty($filters['date_to'])) {
                $args['date_query'][] = ['before' => $filters['date_to'], 'inclusive' => true];
            }
            if (!empty($filters['lists'])) {
                $args['tax_query'][] = ['taxonomy' => 'plover_crm_list', 'terms' => $filters['lists']];
            }
            if (!empty($filters['tags'])) {
                $args['tax_query'][] = ['taxonomy' => 'plover_crm_tag', 'terms' => $filters['tags']];
            }
        }

        $query = new \WP_Query($args);

        if (!$query->have_posts()) {
            wp_send_json_error('No contacts found');
        }

        // Create export file
        $uploadDir = wp_upload_dir();
        $exportDir = $uploadDir['basedir'] . '/' . self::EXPORT_DIR;
        if (!file_exists($exportDir)) wp_mkdir_p($exportDir);

        $filename = 'contacts-' . date('Y-m-d-His') . '.csv';
        $filePath = $exportDir . '/' . $filename;
        $handle = fopen($filePath, 'w');

        // BOM for Excel
        fwrite($handle, "\xEF\xBB\xBF");

        // Headers
        $headers = ['ID', 'Email', 'First Name', 'Last Name', 'Phone', 'City', 'State', 'Country', 'Postal Code', 'Lists', 'Tags'];
        $customFields = $includeCustom ? $this->customFieldsManager->getAllFields() : [];
        foreach ($customFields as $cf) {
            $headers[] = $cf['label'];
        }
        fputcsv($handle, $headers);

        // Data
        $count = 0;
        foreach ($query->posts as $post) {
            $row = [
                $post->ID,
                get_post_meta($post->ID, 'plover_crm_email', true),
                get_post_meta($post->ID, 'plover_crm_first_name', true),
                get_post_meta($post->ID, 'plover_crm_last_name', true),
                get_post_meta($post->ID, 'plover_crm_phone', true),
                get_post_meta($post->ID, 'plover_crm_city', true),
                get_post_meta($post->ID, 'plover_crm_state', true),
                get_post_meta($post->ID, 'plover_crm_country', true),
                get_post_meta($post->ID, 'plover_crm_postal_code', true),
                implode(', ', wp_get_object_terms($post->ID, 'plover_crm_list', ['fields' => 'names']) ?: []),
                implode(', ', wp_get_object_terms($post->ID, 'plover_crm_tag', ['fields' => 'names']) ?: []),
            ];

            foreach ($customFields as $cf) {
                $val = get_post_meta($post->ID, 'plover_crm_cf_' . $cf['slug'], true);
                $row[] = is_array($val) ? implode(', ', $val) : $val;
            }

            fputcsv($handle, $row);
            $count++;
        }

        fclose($handle);

        // Schedule cleanup
        wp_schedule_single_event(time() + 3600, 'plover_crm_cleanup_export', [$filePath]);



        wp_send_json_success([
            'count' => $count,
            'url' => $uploadDir['baseurl'] . '/' . self::EXPORT_DIR . '/' . $filename,
        ]);
    }

    private function autoDetectMapping(array $headers): array
    {
        $aliases = [
            'email' => ['email', 'e-mail', 'email_address', 'emailaddress'],
            'first_name' => ['first_name', 'firstname', 'first', 'given_name'],
            'last_name' => ['last_name', 'lastname', 'last', 'surname', 'family_name'],
            'phone' => ['phone', 'telephone', 'tel', 'mobile', 'cell', 'phone_number'],
            'city' => ['city', 'town'],
            'state' => ['state', 'province', 'region'],
            'country' => ['country'],
            'postal_code' => ['postal_code', 'postalcode', 'zip', 'zipcode', 'postcode'],
        ];

        $mapping = [];
        $customFields = $this->customFieldsManager->getAllFields();

        foreach ($headers as $header) {
            $h = strtolower(trim($header));

            // Check standard fields
            foreach ($aliases as $field => $names) {
                if (in_array($h, $names)) {
                    $mapping[$header] = $field;
                    break;
                }
            }

            // Check custom fields
            if (!isset($mapping[$header])) {
                foreach ($customFields as $cf) {
                    if ($h === strtolower($cf['slug']) || $h === strtolower($cf['label'])) {
                        $mapping[$header] = 'cf_' . $cf['slug'];
                        break;
                    }
                }
            }
        }

        return $mapping;
    }

    private function getAvailableFields(): array
    {
        $fields = [
            ['value' => '_skip', 'label' => '-- Skip --'],
            ['value' => 'email', 'label' => 'Email'],
            ['value' => 'first_name', 'label' => 'First Name'],
            ['value' => 'last_name', 'label' => 'Last Name'],
            ['value' => 'phone', 'label' => 'Phone'],
            ['value' => 'city', 'label' => 'City'],
            ['value' => 'state', 'label' => 'State'],
            ['value' => 'country', 'label' => 'Country'],
            ['value' => 'postal_code', 'label' => 'Postal Code'],
        ];

        foreach ($this->customFieldsManager->getAllFields() as $cf) {
            $fields[] = ['value' => 'cf_' . $cf['slug'], 'label' => $cf['label'] . ' (Custom)'];
        }

        return $fields;
    }
}
