<?php
if (!defined('ABSPATH')) {
    exit;
}

class Manfiet_Google_Sheets_Manager {
    private const TOKEN_OPTION = 'manfiet_gsheets_sync_token';
    private const WEBHOOK_OPTION = 'manfiet_gsheets_webhook_url';
    private const AUTO_SYNC_OPTION = 'manfiet_gsheets_auto_sync';

    public function __construct() {
        add_action('rest_api_init', [$this, 'register_rest_routes']);
    }

    public function get_sync_token(): string {
        $token = (string) get_option(self::TOKEN_OPTION, '');
        if (empty($token)) {
            $token = wp_generate_password(32, false);
            update_option(self::TOKEN_OPTION, $token);
        }
        return $token;
    }

    public function regenerate_sync_token(): string {
        $token = wp_generate_password(32, false);
        update_option(self::TOKEN_OPTION, $token);
        return $token;
    }

    public function get_webhook_url(): string {
        return (string) get_option(self::WEBHOOK_OPTION, '');
    }

    public function is_auto_sync_enabled(): bool {
        return (bool) get_option(self::AUTO_SYNC_OPTION, false);
    }

    public function register_rest_routes(): void {
        $namespace = 'manfi-expense-tracker/v1';

        // Public tokenized CSV endpoints for Google Sheets =IMPORTDATA()
        register_rest_route($namespace, '/export/expenses\.csv', [
            'methods' => 'GET',
            'callback' => [$this, 'export_expenses_csv'],
            'permission_callback' => '__return_true',
        ]);

        register_rest_route($namespace, '/export/invoices\.csv', [
            'methods' => 'GET',
            'callback' => [$this, 'export_invoices_csv'],
            'permission_callback' => '__return_true',
        ]);

        // Settings and Sync endpoints
        register_rest_route($namespace, '/gsheets/settings', [
            [
                'methods' => 'GET',
                'callback' => [$this, 'get_settings_rest'],
                'permission_callback' => [$this, 'check_manage_permission'],
            ],
            [
                'methods' => 'POST',
                'callback' => [$this, 'update_settings_rest'],
                'permission_callback' => [$this, 'check_manage_permission'],
            ],
        ]);

        register_rest_route($namespace, '/gsheets/sync-all', [
            'methods' => 'POST',
            'callback' => [$this, 'trigger_bulk_sync'],
            'permission_callback' => [$this, 'check_manage_permission'],
        ]);
    }

    public function check_manage_permission(): bool {
        return current_user_can('manage_options');
    }

    private function validate_token(WP_REST_Request $request): bool {
        $token = sanitize_text_field($request->get_param('token') ?? '');
        return !empty($token) && hash_equals($this->get_sync_token(), $token);
    }

    private function format_csv_row(array $fields): string {
        $escaped_fields = array_map(function($field) {
            $field = (string) $field;
            if (strpos($field, '"') !== false || strpos($field, ',') !== false || strpos($field, "\n") !== false || strpos($field, "\r") !== false) {
                $field = '"' . str_replace('"', '""', $field) . '"';
            }
            return $field;
        }, $fields);
        return implode(',', $escaped_fields) . "\n";
    }

    public function export_expenses_csv(WP_REST_Request $request) {
        if (!$this->validate_token($request)) {
            return new WP_Error('rest_forbidden', __('Invalid or missing security token.', 'manfi-expense-tracker'), ['status' => 403]);
        }

        $expenses = get_posts([
            'post_type' => 'manfiet_expense',
            'post_status' => 'publish',
            'numberposts' => -1,
            'orderby' => 'date',
            'order' => 'DESC',
        ]);

        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="manfiet-expenses.csv"');
        header('Pragma: no-cache');
        header('Expires: 0');

        $csv_buffer = $this->format_csv_row(['ID', 'Date', 'Title / Description', 'Amount (BDT)', 'Category', 'Vendor', 'Account', 'Remark', 'Created At']);

        foreach ($expenses as $post) {
            $cat_id = (int) get_post_meta($post->ID, '_manfiet_expense_category_id', true);
            $cat_name = $cat_id > 0 ? get_the_title($cat_id) : (string) get_post_meta($post->ID, '_manfiet_expense_category', true);
            $vendor_id = (int) get_post_meta($post->ID, '_manfiet_expense_vendor_id', true);
            $vendor_name = $vendor_id > 0 ? get_the_title($vendor_id) : (string) get_post_meta($post->ID, '_manfiet_expense_vendor', true);
            $account_id = (int) get_post_meta($post->ID, '_manfiet_expense_account_id', true);
            $account_name = $account_id > 0 ? get_the_title($account_id) : (string) get_post_meta($post->ID, '_manfiet_expense_account', true);

            $csv_buffer .= $this->format_csv_row([
                $post->ID,
                (string) get_post_meta($post->ID, '_manfiet_expense_date', true) ?: get_the_date('Y-m-d', $post),
                get_the_title($post),
                number_format((float) get_post_meta($post->ID, '_manfiet_expense_amount', true), 2, '.', ''),
                $cat_name ?: 'General',
                $vendor_name ?: '-',
                $account_name ?: '-',
                (string) get_post_meta($post->ID, '_manfiet_expense_remark', true),
                get_the_date('Y-m-d H:i:s', $post),
            ]);
        }

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Outputting raw CSV buffer for Google Sheets feed.
        echo $csv_buffer;
        exit;
    }

    public function export_invoices_csv(WP_REST_Request $request) {
        if (!$this->validate_token($request)) {
            return new WP_Error('rest_forbidden', __('Invalid or missing security token.', 'manfi-expense-tracker'), ['status' => 403]);
        }

        $invoices = get_posts([
            'post_type' => 'manfiet_invoice',
            'post_status' => 'publish',
            'numberposts' => -1,
            'orderby' => 'date',
            'order' => 'DESC',
        ]);

        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="manfiet-invoices.csv"');
        header('Pragma: no-cache');
        header('Expires: 0');

        $csv_buffer = $this->format_csv_row(['ID', 'Invoice No', 'Date', 'Due Date', 'Client Name', 'Currency', 'Grand Total', 'Paid Amount', 'Balance Due', 'Status', 'Created At']);

        foreach ($invoices as $post) {
            $invoice_id = $post->ID;
            $grand_total = (float) get_post_meta($invoice_id, '_manfiet_invoice_grand_total', true);
            $paid = (float) get_post_meta($invoice_id, '_manfiet_invoice_payment_received_amount', true);
            $due = (float) get_post_meta($invoice_id, '_manfiet_invoice_balance_due', true);
            $status = (string) get_post_meta($invoice_id, '_manfiet_invoice_status', true);
            $client_name = (string) get_post_meta($invoice_id, '_manfiet_invoice_client_name', true);
            if (empty($client_name)) {
                $client_id = (int) get_post_meta($invoice_id, '_manfiet_invoice_client_id', true);
                if ($client_id > 0) {
                    $client_name = get_the_title($client_id);
                }
            }

            $csv_buffer .= $this->format_csv_row([
                $invoice_id,
                (string) get_post_meta($invoice_id, '_manfiet_invoice_no', true),
                (string) get_post_meta($invoice_id, '_manfiet_invoice_date', true),
                (string) get_post_meta($invoice_id, '_manfiet_invoice_due_date', true),
                $client_name ?: 'Client',
                (string) (get_post_meta($invoice_id, '_manfiet_invoice_currency', true) ?: 'BDT'),
                number_format($grand_total, 2, '.', ''),
                number_format($paid, 2, '.', ''),
                number_format($due, 2, '.', ''),
                ucfirst($status ?: 'Pending'),
                get_the_date('Y-m-d H:i:s', $post),
            ]);
        }

        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Outputting raw CSV buffer for Google Sheets feed.
        echo $csv_buffer;
        exit;
    }

    public function get_settings_rest(): WP_REST_Response {
        $token = $this->get_sync_token();
        $rest_url = rest_url('manfi-expense-tracker/v1/export/');

        $expenses_csv_url = add_query_arg(['token' => $token], $rest_url . 'expenses.csv');
        $invoices_csv_url = add_query_arg(['token' => $token], $rest_url . 'invoices.csv');

        return rest_ensure_response([
            'webhook_url' => $this->get_webhook_url(),
            'auto_sync' => $this->is_auto_sync_enabled(),
            'sync_token' => $token,
            'expenses_csv_url' => $expenses_csv_url,
            'invoices_csv_url' => $invoices_csv_url,
            'expenses_formula' => '=IMPORTDATA("' . $expenses_csv_url . '")',
            'invoices_formula' => '=IMPORTDATA("' . $invoices_csv_url . '")',
        ]);
    }

    public function update_settings_rest(WP_REST_Request $request): WP_REST_Response {
        $params = $request->get_json_params();

        if (isset($params['webhook_url'])) {
            update_option(self::WEBHOOK_OPTION, esc_url_raw($params['webhook_url']));
        }

        if (isset($params['auto_sync'])) {
            update_option(self::AUTO_SYNC_OPTION, (bool) $params['auto_sync']);
        }

        if (!empty($params['regenerate_token'])) {
            $this->regenerate_sync_token();
        }

        return $this->get_settings_rest();
    }

    public function trigger_bulk_sync(): WP_REST_Response {
        $webhook_url = $this->get_webhook_url();
        if (empty($webhook_url)) {
            return new WP_REST_Response([
                'success' => false,
                'message' => __('Webhook URL is not configured.', 'manfi-expense-tracker'),
            ], 400);
        }

        // Fire asynchronous non-blocking POST request to user webhook
        $payload = [
            'action' => 'bulk_sync',
            'timestamp' => current_time('mysql'),
            'site_url' => home_url('/'),
            'token' => $this->get_sync_token(),
            'expenses_csv_url' => add_query_arg(['token' => $this->get_sync_token()], rest_url('manfi-expense-tracker/v1/export/expenses.csv')),
            'invoices_csv_url' => add_query_arg(['token' => $this->get_sync_token()], rest_url('manfi-expense-tracker/v1/export/invoices.csv')),
        ];

        wp_remote_post($webhook_url, [
            'method' => 'POST',
            'timeout' => 15,
            'blocking' => false,
            'headers' => ['Content-Type' => 'application/json; charset=utf-8'],
            'body' => wp_json_encode($payload),
        ]);

        return rest_ensure_response([
            'success' => true,
            'message' => __('Bulk sync trigger sent successfully.', 'manfi-expense-tracker'),
        ]);
    }
}
