<?php
// Plugin Check / PHPCS: category-level exclusions with reasons.
// Line-level findings in this file are handled individually below.
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- PaintOps keeps its records in its own custom tables (built by paintops_table()); $wpdb is the supported API for plugin-owned tables, there is no core CRUD alternative, and results are request-scoped.
/**
 * PaintOps - Job Paint Colors
 *
 * What color goes where, how much of it, and what finish, the kind of
 * thing a painter actually needs pulled up on their phone standing in
 * the driveway, not buried in a paragraph of job notes. Deliberately its
 * own table and its own small form (same "own form, own save button"
 * pattern as Job Financials, see paintops_render_job_financial_box()), so
 * adding a color never requires re-saving the whole job.
 *
 * Not gated behind Pro, this is operational info needed to do the
 * job, not a profitability feature.
 */

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

/**
 * Fixed sheen/finish list. A closed list here keeps this consistent for
 * anyone reading it on a job site, the same reasoning used for the
 * expense category dropdown (see job-financials-addon.php).
 */
function paintops_paint_sheen_options(): array {
    return ['Flat/Matte', 'Eggshell', 'Satin', 'Semi-Gloss', 'Gloss', 'Other'];
}

function paintops_get_job_paint_colors(int $job_id): array {
    global $wpdb;

    if ($job_id <= 0) {
        return [];
    }

    return $wpdb->get_results($wpdb->prepare(
        "SELECT id, color_name, product, area, quantity, sheen FROM %i WHERE job_id = %d ORDER BY id ASC", paintops_table('job_paint_colors'), $job_id), ARRAY_A) ?: [];
}

/**
 * Delete-then-reinsert for a single job's paint colors, same approach
 * used elsewhere in this plugin for a job's per-row detail tables,
 * simpler and less error-prone than trying to diff/update individual
 * rows against whatever the form happened to submit.
 */
function paintops_save_job_paint_colors_from_post(int $job_id): void {
    if ($job_id <= 0 || empty($_POST['cs_paint_colors_nonce'])) return;
    if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['cs_paint_colors_nonce'])), 'cs_save_paint_colors_' . $job_id)) return;
    if (!function_exists('paintops_user_can_manage') || !paintops_user_can_manage()) return;

    global $wpdb;
    $table = paintops_table('job_paint_colors');

    $names = $_POST['paint_color_name'] ?? []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- array is iterated below and each element is individually sanitized or cast where consumed
    $products = $_POST['paint_product'] ?? []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- array is iterated below and each element is individually sanitized or cast where consumed
    $areas = $_POST['paint_area'] ?? []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- array is iterated below and each element is individually sanitized or cast where consumed
    $quantities = $_POST['paint_quantity'] ?? []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- array is iterated below and each element is individually sanitized or cast where consumed
    $sheens = $_POST['paint_sheen'] ?? []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- array is iterated below and each element is individually sanitized or cast where consumed

    $wpdb->delete($table, ['job_id' => $job_id], ['%d']);

    $count = max(count((array) $names), count((array) $areas));
    for ($i = 0; $i < $count; $i++) {
        $color_name = sanitize_text_field($names[$i] ?? '');
        $product = sanitize_text_field($products[$i] ?? '');
        $area = sanitize_text_field($areas[$i] ?? '');
        $quantity = sanitize_text_field($quantities[$i] ?? '');
        $sheen = sanitize_text_field($sheens[$i] ?? '');

        if ($color_name === '' && $product === '' && $area === '' && $quantity === '' && $sheen === '') {
            continue; // Skip a fully-blank row rather than saving clutter.
        }

        $wpdb->insert($table, [
            'job_id'     => $job_id,
            'color_name' => $color_name,
            'product'    => $product,
            'area'       => $area,
            'quantity'   => $quantity,
            'sheen'      => $sheen,
        ], ['%d', '%s', '%s', '%s', '%s', '%s']);
    }
}

/**
 * Editable Paint Colors box, staff only. Mirrors the Expenses table
 * add/remove-row pattern from paintops_render_job_financial_box().
 *
 * $embedded=true renders this as a fieldset meant to sit inside another
 * <form> (the Job Edit form) rather than as its own standalone <form>
 * with its own submit button, browsers don't support a <form> nested
 * inside another <form>, and Mike's call was that "Save Paint Colors"
 * being a second, separate save action on the same page was confusing
 * anyway. Embedded mode still emits the job_id/nonce hidden fields (just
 * not wrapped in their own <form>), so the caller's own submit button
 * saves both the job and its paint colors in one request, see
 * paintops_save_job_paint_colors_from_post() call in manage-jobs.php's editEid
 * save handler.
 */
function paintops_render_job_paint_colors_box(int $job_id, bool $embedded = false): void {
    if (!function_exists('paintops_user_can_manage') || !paintops_user_can_manage()) {
        return;
    }

    $colors = paintops_get_job_paint_colors($job_id);
    $sheen_options = paintops_paint_sheen_options();

    $sheen_select = function ($selected = '') use ($sheen_options) {
        $selected = (string) $selected;
        $options = $sheen_options;
        if ($selected !== '' && !in_array($selected, $options, true)) {
            $options[] = $selected; // Preserve an old value not in the current list.
        }
        $html = '<select name="paint_sheen[]" class="cs-sheen-select">';
        $html .= '<option value="">Select sheen</option>';
        foreach ($options as $option) {
            $html .= sprintf(
                '<option value="%s" %s>%s</option>',
                esc_attr($option),
                selected($selected, $option, false),
                esc_html($option)
            );
        }
        $html .= '</select>';
        return $html;
    };

    if (!$colors) {
        $colors = [
            ['color_name' => '', 'area' => '', 'quantity' => '', 'sheen' => ''],
        ];
    }
    ?>
    <div class="cs-financial-box">
        <h3>Paint Colors</h3>
        <p style="color:#777;font-size:13px;margin-top:0;">Color/code, where it's needed (e.g. "Trim and doors" or "Baby's room"), how much, and the sheen - shown to the painter on the job page.</p>
        <?php paintops_enqueue_style('job-paint-colors-box'); ?>

        <?php if (!$embedded): ?><form method="post"><?php endif; ?>
            <input type="hidden" name="job_id" value="<?php echo esc_attr((string) $job_id); ?>">
            <input type="hidden" name="cs_paint_colors_nonce" value="<?php echo esc_attr(wp_create_nonce('cs_save_paint_colors_' . $job_id)); ?>">

            <table class="cs-fin-table" id="cs-paint-color-table">
                <thead>
                    <tr>
                        <th>Color / Code</th>
                        <th>Product</th>
                        <th>Area / Purpose</th>
                        <th>Quantity</th>
                        <th>Sheen</th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ($colors as $color): ?>
                        <tr>
                            <td><input type="text" name="paint_color_name[]" value="<?php echo esc_attr($color['color_name'] ?? ''); ?>" placeholder="i.e. SW Alabaster #7008"></td>
                            <td><input type="text" name="paint_product[]" value="<?php echo esc_attr($color['product'] ?? ''); ?>" placeholder="i.e. SuperPaint"></td>
                            <td><input type="text" name="paint_area[]" value="<?php echo esc_attr($color['area'] ?? ''); ?>" placeholder="i.e. Trim and doors"></td>
                            <td><input type="text" name="paint_quantity[]" value="<?php echo esc_attr($color['quantity'] ?? ''); ?>" placeholder="i.e. 2 gallons"></td>
                            <td><?php echo wp_kses($sheen_select($color['sheen'] ?? ''), paintops_kses_allowed_html(), paintops_kses_protocols()); ?></td>
                            <td><button type="button" class="button cs-remove-row">Remove</button></td>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
            <p><button type="button" class="button" id="cs-add-paint-color">Add Color</button></p>

            <?php if (!$embedded): ?>
            <p><button type="submit" name="cs_save_paint_colors_only" value="1" class="paintops-btn paintops-btn-primary">Save Paint Colors</button></p>
        </form>
            <?php else: ?>
            <p style="color:#777;font-size:13px;">Saves along with the rest of this job when you click Update Job below.</p>
            <?php endif; ?>
    </div>

    <?php
    // The add-row template needs the PHP-built sheen <select> markup, passed
    // as config so the static logic can live in assets/js/job-paint-colors-box.js.
    paintops_enqueue_script(
        'job-paint-colors-box',
        'var paintopsPaintColorsCfg = ' . wp_json_encode(['sheenSelectHtml' => $sheen_select('')]) . ';'
    );
}

/**
 * Read-only Paint Colors list for the job view page, used for both
 * the staff view and the painter-facing view (see includes/job-view.php).
 * Returns '' when there's nothing to show, matching the rest of this
 * plugin's "don't show an empty section" convention.
 */
function paintops_render_paint_colors_list(int $job_id): string {
    $colors = paintops_get_job_paint_colors($job_id);
    $colors = array_filter($colors, static function ($c) {
        return trim((string) ($c['color_name'] ?? '')) !== '' || trim((string) ($c['area'] ?? '')) !== '';
    });

    if (!$colors) {
        return '';
    }

    ob_start();
    ?>
    <div class="paintops-paint-colors">
        <h3 style="margin-bottom:6px;">Paint Colors</h3>
        <?php // cs-fin-table (was WP-admin's "widefat striped", which has no
              // styles on the front end at all): themed headers, and, the
              // real fix, the app's standard phone treatment, thead hidden
              // and each row a stacked label/value card via data-label. The
              // old table kept its 4-column header row side-by-side on
              // phones and pushed the whole page wider than the viewport
              // (Mike 2026-07-22, sideways-scrolling job view). ?>
        <table class="cs-fin-table">
            <thead>
                <tr>
                    <th>Color</th>
                    <th>Product</th>
                    <th>Area / Purpose</th>
                    <th>Quantity</th>
                    <th>Sheen</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($colors as $color): ?>
                    <tr>
                        <td data-label="Color"><?php echo esc_html($color['color_name'] ?? ''); ?></td>
                        <td data-label="Product"><?php echo esc_html($color['product'] ?? ''); ?></td>
                        <td data-label="Area / Purpose"><?php echo esc_html($color['area'] ?? ''); ?></td>
                        <td data-label="Quantity"><?php echo esc_html($color['quantity'] ?? ''); ?></td>
                        <td data-label="Sheen"><?php echo esc_html($color['sheen'] ?? ''); ?></td>
                    </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
    <?php
    return ob_get_clean();
}
