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

class Manfiet_Budget_Alerts {
    private $table;

    public function __construct() {
        global $wpdb;
        $this->table = $wpdb->prefix . 'manfiet_expenses';

        add_action('manfiet_check_budget_alert', [$this, 'check_budget_alert']);
        add_action('rest_api_init', [$this, 'register_rest_routes']);
        add_action('admin_notices', [$this, 'render_budget_usage_notice']);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_budget_styles']);
    }

    private function user_can_manage_expenses() {
        return current_user_can('manage_expenses') || current_user_can('manage_options');
    }

    private function get_budget_meta_key($period) {
        return 'manfiet_' . $period . '_budget_limit';
    }

    private function get_default_budget($period) {
        $monthly_default = (int) get_option('manfiet_default_budget', 500);
        $weekly_default = (int) get_option('manfiet_default_weekly_budget', 125);
        $yearly_default = (int) get_option('manfiet_default_yearly_budget', 6000);

        if ($period === 'week') {
            return max(1, $weekly_default);
        }

        if ($period === 'year') {
            return max(1, $yearly_default);
        }

        return max(1, $monthly_default);
    }

    private function get_user_budget($user_id, $period) {
        $value = (int) get_user_meta($user_id, $this->get_budget_meta_key($period), true);

        if ($period === 'month' && $value <= 0) {
            $legacy_monthly = (int) get_user_meta($user_id, 'manfiet_monthly_budget_limit', true);
            if ($legacy_monthly > 0) {
                return $legacy_monthly;
            }
        }

        if ($value <= 0) {
            return $this->get_default_budget($period);
        }

        return $value;
    }

    private function get_spent_for_period($user_id, $period) {
        global $wpdb;
        $table = $this->table;
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Budget summary queries run on plugin-owned table.

        if ($period === 'week') {
            $start = gmdate('Y-m-d', strtotime('monday this week'));
            $end = gmdate('Y-m-d', strtotime('sunday this week'));
            return (float) $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT COALESCE(SUM(amount), 0) FROM %i WHERE user_id = %d AND date BETWEEN %s AND %s",
                    $table,
                    $user_id,
                    $start,
                    $end
                )
            );
        }

        if ($period === 'year') {
            $current_year = gmdate('Y');
            return (float) $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT COALESCE(SUM(amount), 0) FROM %i WHERE user_id = %d AND YEAR(date) = %s",
                    $table,
                    $user_id,
                    $current_year
                )
            );
        }

        $current_month = gmdate('Y-m');
        $spent = (float) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT COALESCE(SUM(amount), 0) FROM %i WHERE user_id = %d AND DATE_FORMAT(date, '%%Y-%%m') = %s",
                $table,
                $user_id,
                $current_month
            )
        );
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

        return $spent;
    }

    // Check spending against weekly, monthly, and yearly budgets and send alert.
    public function check_budget_alert() {
        $users = get_users(['fields' => ['ID']]);
        $period_labels = [
            'week' => __('week', 'manfi-expense-tracker'),
            'month' => __('month', 'manfi-expense-tracker'),
            'year' => __('year', 'manfi-expense-tracker'),
        ];

        foreach ($users as $user) {
            $user_id = $user->ID;
            $exceeded_lines = [];

            foreach (['week', 'month', 'year'] as $period) {
                $budget_limit = $this->get_user_budget($user_id, $period);
                $spent = $this->get_spent_for_period($user_id, $period);

                if ($spent <= $budget_limit) {
                    continue;
                }

                $exceeded_lines[] = sprintf(
                    /* translators: 1: budget period label, 2: amount spent, 3: budget limit. */
                    __('%1$s: spent $%2$s, budget $%3$s', 'manfi-expense-tracker'),
                    $period_labels[$period],
                    number_format_i18n($spent, 2),
                    number_format_i18n($budget_limit, 2)
                );
            }

            if (empty($exceeded_lines)) {
                continue;
            }

            $user_email = get_userdata($user_id)->user_email;
            $subject = __('Manfi Expense Tracker: Budget Exceeded!', 'manfi-expense-tracker');
            $message = __('Alert! You exceeded your budget limits for the following periods:', 'manfi-expense-tracker');
            $message .= "\n\n- " . implode("\n- ", $exceeded_lines);

            $sender_name = get_option('manfiet_email_sender_name', 'Manfi Expense Tracker');
            $domain = wp_parse_url(get_site_url(), PHP_URL_HOST);
            $default_email = 'no-reply@' . ($domain ? $domain : 'manfietracker.com');
            $sender_email = get_option('manfiet_email_sender_address', $default_email);

            $headers = [
                'Content-Type: text/plain; charset=UTF-8',
                sprintf('From: %s <%s>', $sender_name, $sender_email)
            ];
            wp_mail($user_email, $subject, $message, $headers);
        }
    }

    // Register REST API for User Budget Management
    public function register_rest_routes() {
        register_rest_route('manfi-expense-tracker/v1', '/budget', [
            'methods' => 'POST',
            'callback' => [$this, 'update_budget'],
            'permission_callback' => [$this, 'is_user_logged_in_permission'],
        ]);

        register_rest_route('manfi-expense-tracker/v1', '/budget', [
            'methods' => 'GET',
            'callback' => [$this, 'get_budget'],
            'permission_callback' => [$this, 'is_user_logged_in_permission'],
        ]);
    }

    public function is_user_logged_in_permission() {
        return is_user_logged_in() && current_user_can('read');
    }

    public function update_budget(WP_REST_Request $request) {
        $user_id = get_current_user_id();
        $period = sanitize_text_field((string) $request->get_param('period'));
        $budget = absint($request->get_param('budget'));
        $budgets = $request->get_param('budgets');

        if (!$user_id) {
            return new WP_Error(
                'manfiet_unauthorized',
                __('Unauthorized request.', 'manfi-expense-tracker'),
                ['status' => 401]
            );
        }

        $allowed_periods = ['week', 'month', 'year'];

        if (is_array($budgets)) {
            foreach ($allowed_periods as $allowed_period) {
                if (!isset($budgets[$allowed_period])) {
                    continue;
                }

                $value = absint($budgets[$allowed_period]);
                if ($value <= 0) {
                    return new WP_Error(
                        'manfiet_invalid_budget',
                        __('Each budget must be greater than zero.', 'manfi-expense-tracker'),
                        ['status' => 400]
                    );
                }

                update_user_meta($user_id, $this->get_budget_meta_key($allowed_period), $value);
            }

            return rest_ensure_response(['message' => __('Budgets updated successfully', 'manfi-expense-tracker')]);
        }

        if (!in_array($period, $allowed_periods, true)) {
            return new WP_Error(
                'manfiet_invalid_budget_period',
                __('Budget period must be week, month, or year.', 'manfi-expense-tracker'),
                ['status' => 400]
            );
        }

        if ($budget <= 0) {
            return new WP_Error(
                'manfiet_invalid_budget',
                __('Budget must be greater than zero.', 'manfi-expense-tracker'),
                ['status' => 400]
            );
        }

        $updated = update_user_meta($user_id, $this->get_budget_meta_key($period), $budget);

        if ($updated === false) {
            return new WP_Error(
                'manfiet_budget_update_failed',
                __('Failed to update budget.', 'manfi-expense-tracker'),
                ['status' => 500]
            );
        }

        return rest_ensure_response(['message' => __('Budget updated successfully', 'manfi-expense-tracker')]);
    }

    public function get_budget() {
        $user_id = get_current_user_id();
        $periods = ['week', 'month', 'year'];
        $budgets = [];
        $spent = [];
        $usage = [];

        foreach ($periods as $period) {
            $period_budget = $this->get_user_budget($user_id, $period);
            $period_spent = $this->get_spent_for_period($user_id, $period);
            $period_usage = $period_budget > 0 ? round(($period_spent / $period_budget) * 100, 2) : 0;

            $budgets[$period] = $period_budget;
            $spent[$period] = $period_spent;
            $usage[$period] = $period_usage;
        }

        return rest_ensure_response([
            'budgets' => $budgets,
            'spent' => $spent,
            'usage' => $usage,
        ]);
    }

    public function enqueue_budget_styles() {
        if (!$this->user_can_manage_expenses()) {
            return;
        }

        $styles = '
            .manfiet-budget-notice{
                border:1px solid #dbe4f2;
                border-left-width:6px;
                border-radius:10px;
                background:#ffffff;
                box-shadow:0 8px 18px rgba(15,23,42,.06);
                padding:10px 14px;
                margin:10px 0;
            }
            .manfiet-budget-notice p{margin:0;color:#0f172a;line-height:1.45;}
            .manfiet-budget-notice .manfiet-budget-title{font-weight:700;margin-right:6px;}
            .manfiet-budget-notice--warning{border-left-color:#f59e0b;background:linear-gradient(90deg,#fffbeb 0,#ffffff 24%);}
            .manfiet-budget-notice--danger{border-left-color:#ef4444;background:linear-gradient(90deg,#fef2f2 0,#ffffff 24%);}
        ';

        wp_register_style('manfiet-budget-alerts-styles', false, [], MANFIET_EXPENSE_TRACKER_VERSION);
        wp_enqueue_style('manfiet-budget-alerts-styles');
        wp_add_inline_style('manfiet-budget-alerts-styles', $styles);
    }

    public function render_budget_usage_notice() {
        if (!$this->user_can_manage_expenses()) {
            return;
        }

        $user_id = get_current_user_id();
        if (!$user_id) {
            return;
        }

        $periods = ['week', 'month', 'year'];
        foreach ($periods as $period) {
            $budget = $this->get_user_budget($user_id, $period);
            $spent = $this->get_spent_for_period($user_id, $period);
            if ($budget <= 0) {
                continue;
            }

            $usage = round(($spent / $budget) * 100, 2);
            if ($usage < 70) {
                continue;
            }

            $notice_class = $usage >= 100 ? 'manfiet-budget-notice manfiet-budget-notice--danger' : 'manfiet-budget-notice manfiet-budget-notice--warning';
            $label = ucfirst($period);
            $title = sprintf(
                /* translators: %s: budget period label. */
                __('%s Budget Alert', 'manfi-expense-tracker'),
                $label
            );
            $details = sprintf(
                /* translators: 1: usage percentage, 2: amount spent, 3: budget amount. */
                __('%1$s%% spent (%2$s of %3$s).', 'manfi-expense-tracker'),
                number_format_i18n($usage, 2),
                number_format_i18n($spent, 2),
                number_format_i18n($budget, 2)
            );

            echo '<div class="' . esc_attr($notice_class) . '"><p><span class="manfiet-budget-title">' . esc_html($title) . ':</span>' . esc_html($details) . '</p></div>';
        }
    }
}
