<?php
/**
 * VAT codes, service mode (dine-in / takeaway), and order breakdown helpers.
 *
 * @package Maca_Menu_List
 */

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

/**
 * How the restaurant primarily serves food (determines food VAT rate).
 *
 * @return array<int, string>
 */
function maca_menulist_get_service_modes() {
    return array('dine_in', 'takeaway');
}

/**
 * Current service mode: dine_in or takeaway.
 *
 * @return string
 */
function maca_menulist_get_service_mode() {
    $mode = sanitize_key((string) get_option('maca_menulist_service_mode', 'dine_in'));

    if (!in_array($mode, maca_menulist_get_service_modes(), true)) {
        return 'dine_in';
    }

    return $mode;
}

/**
 * Dish VAT codes (food uses service mode rate; alcohol uses alcohol rate).
 *
 * @return array<string, string> code => translated label
 */
function maca_menulist_get_dish_vat_code_options() {
    return array(
        'food' => __('Food / non-alcoholic', 'maca-restu-pro'),
        'alcohol' => __('Alcohol', 'maca-restu-pro'),
    );
}

/**
 * Sanitize dish VAT code.
 *
 * @param mixed $code Raw code.
 * @return string food|alcohol
 */
function maca_menulist_sanitize_dish_vat_code($code) {
    $code = sanitize_key((string) $code);

    return array_key_exists($code, maca_menulist_get_dish_vat_code_options()) ? $code : 'food';
}

/**
 * Parse a dish VAT code from admin or CSV input (codes, labels, Swedish aliases).
 *
 * @param mixed  $raw     Raw value from CSV or form.
 * @param string $default Default when empty or unknown.
 * @return string food|alcohol
 */
function maca_menulist_parse_dish_vat_code($raw, $default = 'food') {
    $raw = trim((string) $raw);
    if ($raw === '') {
        return maca_menulist_sanitize_dish_vat_code($default);
    }

    $key = sanitize_key($raw);
    if (array_key_exists($key, maca_menulist_get_dish_vat_code_options())) {
        return $key;
    }

    $normalized = function_exists('remove_accents') ? remove_accents($raw) : $raw;
    $normalized = strtolower($normalized);
    $normalized = preg_replace('/[^a-z0-9]+/', '_', $normalized);
    $normalized = trim((string) $normalized, '_');

    $aliases = array(
        'food' => array(
            'food',
            'mat',
            'mat_alkoholfritt',
            'non_alcoholic',
            'alkoholfritt',
            'livsmedel',
        ),
        'alcohol' => array(
            'alcohol',
            'alkohol',
            'vin',
            'ol',
            'sprit',
        ),
    );

    foreach ($aliases as $code => $keys) {
        if (in_array($normalized, $keys, true) || in_array($key, $keys, true)) {
            return $code;
        }
    }

    foreach (maca_menulist_get_dish_vat_code_options() as $code => $label) {
        $label_normalized = function_exists('remove_accents') ? remove_accents($label) : $label;
        $label_normalized = strtolower($label_normalized);
        $label_normalized = preg_replace('/[^a-z0-9]+/', '_', $label_normalized);
        $label_normalized = trim((string) $label_normalized, '_');

        if ($normalized === $label_normalized) {
            return $code;
        }
    }

    return maca_menulist_sanitize_dish_vat_code($default);
}

/**
 * VAT rate category keys stored in options.
 *
 * @return array<int, string>
 */
function maca_menulist_get_vat_rate_categories() {
    return array('dine_in', 'takeaway', 'alcohol');
}

/**
 * Option name for a stored VAT rate field.
 *
 * @param string $category dine_in|takeaway|alcohol
 * @param string $field    current|upcoming|upcoming_date
 * @return string
 */
function maca_menulist_vat_rate_option_name($category, $field = 'current') {
    $category = sanitize_key($category);
    $bases = array(
        'dine_in' => 'maca_menulist_vat_rate_dine_in',
        'takeaway' => 'maca_menulist_vat_rate_takeaway',
        'alcohol' => 'maca_menulist_vat_rate_alcohol',
    );

    if (!isset($bases[$category])) {
        return '';
    }

    if ($field === 'upcoming') {
        return $bases[$category] . '_upcoming';
    }

    if ($field === 'upcoming_date') {
        return $bases[$category] . '_upcoming_date';
    }

    return $bases[$category];
}

/**
 * Sanitize scheduled VAT effective date (Y-m-d in site timezone).
 *
 * @param mixed $value Raw date.
 * @return string Empty when invalid.
 */
function maca_menulist_sanitize_vat_effective_date($value) {
    $value = trim((string) $value);
    if ($value === '') {
        return '';
    }

    $date = DateTimeImmutable::createFromFormat('Y-m-d', $value, wp_timezone());
    if (!$date || $date->format('Y-m-d') !== $value) {
        return '';
    }

    return $value;
}

/**
 * Start-of-day timestamp for a VAT effective date in the site timezone.
 *
 * @param string $date_ymd Y-m-d.
 * @return int|false Unix timestamp or false when invalid.
 */
function maca_menulist_vat_rate_effective_timestamp($date_ymd) {
    $date_ymd = maca_menulist_sanitize_vat_effective_date($date_ymd);
    if ($date_ymd === '') {
        return false;
    }

    $date = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $date_ymd . ' 00:00:00', wp_timezone());
    if (!$date) {
        return false;
    }

    return $date->getTimestamp();
}

/**
 * Stored (admin) VAT rate — not resolved against upcoming schedule.
 *
 * @param string $category dine_in|takeaway|alcohol
 * @return string
 */
function maca_menulist_get_stored_vat_rate($category) {
    $option = maca_menulist_vat_rate_option_name($category, 'current');
    if ($option === '') {
        return '';
    }

    return maca_menulist_sanitize_vat_rate(get_option($option, ''));
}

/**
 * Scheduled upcoming VAT rate for a category.
 *
 * @param string $category dine_in|takeaway|alcohol
 * @return string
 */
function maca_menulist_get_stored_vat_rate_upcoming($category) {
    $option = maca_menulist_vat_rate_option_name($category, 'upcoming');
    if ($option === '') {
        return '';
    }

    return maca_menulist_sanitize_vat_rate(get_option($option, ''));
}

/**
 * Date from which the upcoming VAT rate applies (site timezone, start of day).
 *
 * @param string $category dine_in|takeaway|alcohol
 * @return string Y-m-d or empty.
 */
function maca_menulist_get_stored_vat_rate_upcoming_date($category) {
    $option = maca_menulist_vat_rate_option_name($category, 'upcoming_date');
    if ($option === '') {
        return '';
    }

    return maca_menulist_sanitize_vat_effective_date(get_option($option, ''));
}

/**
 * Resolve VAT rate for a category at a point in time.
 *
 * Uses stored current rate before the scheduled date; upcoming rate on/after that date.
 * Does not mutate stored options (historical orders stay correct).
 *
 * @param string   $category dine_in|takeaway|alcohol
 * @param int|null $at       Unix timestamp; null = now (site time).
 * @return string
 */
function maca_menulist_resolve_vat_rate_for_category($category, $at = null) {
    $stored = maca_menulist_get_stored_vat_rate($category);
    $upcoming = maca_menulist_get_stored_vat_rate_upcoming($category);
    $date = maca_menulist_get_stored_vat_rate_upcoming_date($category);

    if ($upcoming !== '' && $date !== '') {
        $effective_ts = maca_menulist_vat_rate_effective_timestamp($date);
        if ($effective_ts !== false) {
            if ($at === null) {
                $at = (int) current_time('timestamp');
            }

            if ($at >= $effective_ts) {
                return $upcoming;
            }
        }
    }

    return $stored;
}

/**
 * Timestamp for VAT on a table order (paid time preferred).
 *
 * @param object $order Order row.
 * @return int|null
 */
function maca_menulist_get_order_vat_timestamp($order) {
    if (!empty($order->paid_at)) {
        $paid_ts = maca_menulist_wp_mysql_to_timestamp((string) $order->paid_at);
        if ($paid_ts !== false) {
            return $paid_ts;
        }
    }

    if (!empty($order->created_at)) {
        $created_ts = maca_menulist_wp_mysql_to_timestamp((string) $order->created_at);
        if ($created_ts !== false) {
            return $created_ts;
        }
    }

    return null;
}

/**
 * Short summary of VAT rates for menu footer (current + scheduled changes).
 *
 * @return string
 */
function maca_menulist_build_vat_rate_summary_text() {
    $parts = array();
    $now = (int) current_time('timestamp');

    $offering = function_exists('maca_menulist_get_offering_mode') ? maca_menulist_get_offering_mode() : '';
    $category_keys = array('dine_in', 'takeaway', 'alcohol');
    if ($offering === 'takeaway_only') {
        $category_keys = array('takeaway', 'alcohol');
    } elseif ($offering === 'dine_in_only') {
        $category_keys = array('dine_in', 'alcohol');
    }

    $categories = array(
        'dine_in' => static function ($rate, $from_date, $from_rate) {
            if ($from_date !== '' && $from_rate !== '') {
                return sprintf(
                    /* translators: 1: current VAT rate, 2: effective date, 3: upcoming VAT rate */
                    __('Dine-in %1$s VAT (from %2$s: %3$s).', 'maca-restu-pro'),
                    maca_menulist_format_vat_rate_label($rate),
                    $from_date,
                    maca_menulist_format_vat_rate_label($from_rate)
                );
            }

            /* translators: %s: VAT rate, e.g. 12% */
            return sprintf(__('Dine-in %s VAT.', 'maca-restu-pro'), maca_menulist_format_vat_rate_label($rate));
        },
        'takeaway' => static function ($rate, $from_date, $from_rate) {
            if ($from_date !== '' && $from_rate !== '') {
                return sprintf(
                    /* translators: 1: current VAT rate, 2: effective date, 3: upcoming VAT rate */
                    __('Takeaway %1$s VAT (from %2$s: %3$s).', 'maca-restu-pro'),
                    maca_menulist_format_vat_rate_label($rate),
                    $from_date,
                    maca_menulist_format_vat_rate_label($from_rate)
                );
            }

            /* translators: %s: VAT rate, e.g. 6% */
            return sprintf(__('Takeaway %s VAT.', 'maca-restu-pro'), maca_menulist_format_vat_rate_label($rate));
        },
        'alcohol' => static function ($rate, $from_date, $from_rate) {
            if ($from_date !== '' && $from_rate !== '') {
                return sprintf(
                    /* translators: 1: current VAT rate, 2: effective date, 3: upcoming VAT rate */
                    __('Alcohol %1$s VAT (from %2$s: %3$s).', 'maca-restu-pro'),
                    maca_menulist_format_vat_rate_label($rate),
                    $from_date,
                    maca_menulist_format_vat_rate_label($from_rate)
                );
            }

            /* translators: %s: VAT rate, e.g. 25% */
            return sprintf(__('Alcohol %s VAT.', 'maca-restu-pro'), maca_menulist_format_vat_rate_label($rate));
        },
    );

    foreach ($category_keys as $category) {
        if (!isset($categories[$category])) {
            continue;
        }
        $formatter = $categories[$category];
        $effective = maca_menulist_resolve_vat_rate_for_category($category, $now);
        if ($effective === '') {
            continue;
        }

        $upcoming = maca_menulist_get_stored_vat_rate_upcoming($category);
        $date_ymd = maca_menulist_get_stored_vat_rate_upcoming_date($category);
        $from_date = '';
        $from_rate = '';

        if ($upcoming !== '' && $date_ymd !== '') {
            $effective_ts = maca_menulist_vat_rate_effective_timestamp($date_ymd);
            if ($effective_ts !== false && $now < $effective_ts) {
                $from_date = wp_date(get_option('date_format'), $effective_ts);
                $from_rate = $upcoming;
                $effective = maca_menulist_get_stored_vat_rate($category);
                if ($effective === '') {
                    $effective = $upcoming;
                }
            }
        }

        $parts[] = $formatter($effective, $from_date, $from_rate);
    }

    return implode(' ', $parts);
}

/**
 * Admin display for one VAT rate category (current + optional scheduled change).
 *
 * @param string $category dine_in|takeaway|alcohol
 * @return string
 */
function maca_menulist_admin_vat_rate_setting_line($category) {
    $effective = maca_menulist_resolve_vat_rate_for_category($category);
    $stored = maca_menulist_get_stored_vat_rate($category);
    $upcoming = maca_menulist_get_stored_vat_rate_upcoming($category);
    $date_ymd = maca_menulist_get_stored_vat_rate_upcoming_date($category);

    if ($effective === '' && $stored === '' && $upcoming === '') {
        return '—';
    }

    $rate_text = $effective !== '' ? maca_menulist_format_vat_rate_label($effective) : '—';

    if ($upcoming !== '' && $date_ymd !== '') {
        $effective_ts = maca_menulist_vat_rate_effective_timestamp($date_ymd);
        $now = (int) current_time('timestamp');
        if ($effective_ts !== false && $now < $effective_ts) {
            $stored_label = $stored !== '' ? maca_menulist_format_vat_rate_label($stored) : $rate_text;
            $upcoming_label = maca_menulist_format_vat_rate_label($upcoming);
            $date_label = wp_date(get_option('date_format'), $effective_ts);

            /* translators: 1: current VAT rate, 2: effective date, 3: upcoming VAT rate */
            return sprintf(__('%1$s (from %2$s: %3$s)', 'maca-restu-pro'), $stored_label, $date_label, $upcoming_label);
        }
    }

    return $rate_text;
}

/**
 * Read-only VAT settings summary for dish admin screens.
 *
 * @return void
 */
function maca_menulist_render_admin_vat_settings_summary() {
    static $styles_printed = false;

    $settings_url = admin_url('admin.php?page=maca-restu-settings&tab=restaurant');
    $service_mode = maca_menulist_get_service_mode();
    $service_labels = array(
        'dine_in' => __('Dine-in (eat on premises)', 'maca-restu-pro'),
        'takeaway' => __('Takeaway', 'maca-restu-pro'),
    );
    $service_label = isset($service_labels[ $service_mode ]) ? $service_labels[ $service_mode ] : $service_mode;
    $vat_number = maca_menulist_get_vat_number();

    $rows = array(
        __('Service type', 'maca-restu-pro') => $service_label,
        __('Dine-in (eat on premises)', 'maca-restu-pro') => maca_menulist_admin_vat_rate_setting_line('dine_in'),
        __('Takeaway', 'maca-restu-pro') => maca_menulist_admin_vat_rate_setting_line('takeaway'),
        __('Alcohol', 'maca-restu-pro') => maca_menulist_admin_vat_rate_setting_line('alcohol'),
    );

    if ($vat_number !== '') {
        $rows = array(
            __('VAT number', 'maca-restu-pro') => $vat_number,
        ) + $rows;
    }

    if (!$styles_printed) {
        $styles_printed = true;
        echo '<style>
            .maca-admin-vat-summary {
                margin: 12px 0 20px;
                padding: 12px 16px;
                max-width: 720px;
                background: #fff;
                border: 1px solid #c3c4c7;
                border-left-width: 4px;
                border-left-color: #2271b1;
                box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
            }
            .maca-admin-vat-summary__head {
                display: flex;
                flex-wrap: wrap;
                align-items: center;
                gap: 8px 12px;
                margin-bottom: 10px;
            }
            .maca-admin-vat-summary__head h2 {
                margin: 0;
                font-size: 14px;
                line-height: 1.4;
            }
            .maca-admin-vat-summary__table {
                width: 100%;
                border-collapse: collapse;
                margin: 0;
            }
            .maca-admin-vat-summary__table th,
            .maca-admin-vat-summary__table td {
                padding: 4px 8px 4px 0;
                vertical-align: top;
                font-size: 13px;
                line-height: 1.5;
            }
            .maca-admin-vat-summary__table th {
                width: 220px;
                font-weight: 600;
                color: #1d2327;
            }
            .maca-admin-vat-summary__desc {
                margin: 8px 0 0;
                color: #646970;
                font-size: 12px;
            }
        </style>';
    }

    echo '<div class="maca-admin-vat-summary">';
    echo '<div class="maca-admin-vat-summary__head">';
    echo '<h2>' . esc_html__('VAT settings', 'maca-restu-pro') . '</h2>';
    echo '<a href="' . esc_url($settings_url) . '" class="button button-secondary button-small">' . esc_html__('Edit VAT settings', 'maca-restu-pro') . '</a>';
    echo '</div>';
    echo '<table class="maca-admin-vat-summary__table" role="presentation">';
    foreach ($rows as $label => $value) {
        echo '<tr><th scope="row">' . esc_html($label) . '</th><td>' . esc_html($value) . '</td></tr>';
    }
    echo '</table>';
    echo '<p class="maca-admin-vat-summary__desc">' . esc_html__('Applies to dish VAT codes, menu footer, and order confirmations. Food / non-alcoholic dishes use the rate for your service type.', 'maca-restu-pro') . '</p>';
    echo '</div>';
}

/**
 * VAT percentage for a dish VAT code (empty string when rate not configured).
 *
 * @param string   $code food|alcohol
 * @param int|null $at   Unix timestamp for scheduled rates; null = now.
 * @return string
 */
function maca_menulist_get_vat_rate_for_code($code, $at = null, $service_mode = null) {
    $code = maca_menulist_sanitize_dish_vat_code($code);

    if ($code === 'alcohol') {
        return maca_menulist_get_vat_rate_alcohol($at);
    }

    if ($service_mode === null) {
        $service_mode = maca_menulist_get_service_mode();
    } else {
        $service_mode = sanitize_key((string) $service_mode);
        if (!in_array($service_mode, maca_menulist_get_service_modes(), true)) {
            $service_mode = maca_menulist_get_service_mode();
        }
    }

    if ($service_mode === 'takeaway') {
        return maca_menulist_get_vat_rate_takeaway($at);
    }

    return maca_menulist_get_vat_rate_dine_in($at);
}

/**
 * VAT code for a dish ID.
 *
 * @param int $dish_id Dish ID.
 * @return string
 */
function maca_menulist_get_dish_vat_code($dish_id) {
    $dish_id = absint($dish_id);
    if ($dish_id <= 0) {
        return 'food';
    }

    $dish = maca_menulist_db_get_dish($dish_id);
    if (!$dish || empty($dish->vat_code)) {
        return 'food';
    }

    return maca_menulist_sanitize_dish_vat_code($dish->vat_code);
}

/**
 * Split gross (incl. VAT) into net and VAT amounts.
 *
 * @param float  $gross Gross amount.
 * @param string $rate_percent VAT rate, e.g. 12.
 * @return array{gross: float, net: float, vat: float, rate: string}
 */
function maca_menulist_split_gross_vat($gross, $rate_percent) {
    $gross = round((float) $gross, 2);
    $rate = maca_menulist_sanitize_vat_rate($rate_percent);

    if ($gross <= 0 || $rate === '') {
        return array(
            'gross' => $gross,
            'net' => $gross,
            'vat' => 0.0,
            'rate' => $rate,
        );
    }

    $factor = 1 + ((float) $rate / 100);
    $net = round($gross / $factor, 2);
    $vat = round($gross - $net, 2);

    return array(
        'gross' => $gross,
        'net' => $net,
        'vat' => $vat,
        'rate' => $rate,
    );
}

/**
 * Human label for a VAT rate in emails and admin.
 *
 * @param string $rate Percent string.
 * @param string $code Optional dish VAT code for context.
 * @return string
 */
function maca_menulist_get_vat_rate_display_label($rate, $code = '', $service_mode = null) {
    $rate_label = maca_menulist_format_vat_rate_label($rate);
    if ($rate_label === '') {
        return '';
    }

    if ($code === 'alcohol') {
        /* translators: %s: VAT rate, e.g. 25% */
        return sprintf(__('Alcohol %s', 'maca-restu-pro'), $rate_label);
    }

    if ($service_mode === null) {
        $service_mode = maca_menulist_get_service_mode();
    } else {
        $service_mode = sanitize_key((string) $service_mode);
    }

    if ($service_mode === 'takeaway') {
        /* translators: %s: VAT rate, e.g. 6% */
        return sprintf(__('Takeaway %s', 'maca-restu-pro'), $rate_label);
    }

    /* translators: %s: VAT rate, e.g. 12% */
    return sprintf(__('Dine-in %s', 'maca-restu-pro'), $rate_label);
}

/**
 * Build VAT breakdown for a paid table order (prices assumed incl. VAT).
 *
 * @param object $order Order with ->lines.
 * @return array<string, mixed>
 */
function maca_menulist_build_order_vat_breakdown($order) {
    $lines_out = array();
    $by_rate = array();
    $vat_at = maca_menulist_get_order_vat_timestamp($order);
    $order_service_mode = function_exists('maca_menulist_get_order_service_mode')
        ? maca_menulist_get_order_service_mode($order)
        : maca_menulist_get_service_mode();

    if (!empty($order->lines) && is_array($order->lines)) {
        foreach ($order->lines as $line) {
            if ($line->price === null || $line->price === '') {
                continue;
            }

            $qty = max(1, (int) $line->qty);
            $gross = round((float) $line->price * $qty, 2);
            if ($gross <= 0) {
                continue;
            }

            $dish_id = isset($line->dish_id) ? absint($line->dish_id) : 0;
            $vat_code = maca_menulist_get_dish_vat_code($dish_id);
            $rate = maca_menulist_get_vat_rate_for_code($vat_code, $vat_at, $order_service_mode);
            $split = maca_menulist_split_gross_vat($gross, $rate);

            $lines_out[] = array(
                'title' => (string) $line->title,
                'qty' => $qty,
                'gross' => $gross,
                'gross_label' => maca_menulist_format_price($gross),
                'vat_code' => $vat_code,
                'rate' => $rate,
                'rate_label' => maca_menulist_get_vat_rate_display_label($rate, $vat_code, $order_service_mode),
                'net' => $split['net'],
                'vat' => $split['vat'],
            );

            $rate_key = $rate !== '' ? $rate : 'unknown';
            if (!isset($by_rate[$rate_key])) {
                $by_rate[$rate_key] = array(
                    'rate' => $rate,
                    'rate_label' => maca_menulist_get_vat_rate_display_label($rate, $vat_code, $order_service_mode),
                    'gross' => 0.0,
                    'net' => 0.0,
                    'vat' => 0.0,
                );
            }

            $by_rate[$rate_key]['gross'] += $split['gross'];
            $by_rate[$rate_key]['net'] += $split['net'];
            $by_rate[$rate_key]['vat'] += $split['vat'];
        }
    }

    $tip_amount = maca_menulist_get_order_tip_amount($order);
    if ($tip_amount > 0) {
        $lines_out[] = array(
            'title' => __('Tip', 'maca-restu-pro'),
            'qty' => 1,
            'gross' => $tip_amount,
            'gross_label' => maca_menulist_format_price($tip_amount),
            'vat_code' => 'tip',
            'rate' => '',
            'rate_label' => '',
            'net' => $tip_amount,
            'vat' => 0.0,
            'is_tip' => true,
        );
    }

    $total_gross = maca_menulist_order_payment_total($order);
    $total_vat = 0.0;
    $total_net = 0.0;

    foreach ($by_rate as $bucket) {
        $total_vat += $bucket['vat'];
        $total_net += $bucket['net'];
    }

    if ($tip_amount > 0) {
        $total_net += $tip_amount;
    }

    ksort($by_rate, SORT_NATURAL);

    return array(
        'lines' => $lines_out,
        'by_rate' => array_values($by_rate),
        'total_gross' => $total_gross,
        'total_gross_label' => maca_menulist_format_price($total_gross),
        'total_net' => round($total_net, 2),
        'total_vat' => round($total_vat, 2),
        'service_mode' => $order_service_mode,
    );
}
