<?php
declare(strict_types=1);
ini_set('display_errors', '0');

require_once __DIR__ . '/../includes/console_shell.php';
require_login();

$pageLink = 'payroll/ecr-configuration.php';
$acl = require_acl('can_view', $pageLink);
$errors = [];
$flash = $_SESSION['flash_ecr_configuration'] ?? null;
unset($_SESSION['flash_ecr_configuration']);

function ecr_stmt(mysqli $con, string $sql): mysqli_stmt
{
    $stmt = $con->prepare($sql);
    if (!$stmt) {
        throw new RuntimeException('Unable to prepare ECR configuration query.');
    }
    return $stmt;
}

function ecr_options(mysqli $con, string $sql): array
{
    $rows = [];
    $stmt = ecr_stmt($con, $sql);
    $stmt->execute();
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        $rows[] = $row;
    }
    $stmt->close();
    return $rows;
}

function ecr_columns(mysqli $con, string $table): array
{
    static $cache = [];
    if (isset($cache[$table])) {
        return $cache[$table];
    }
    if ($table !== 'jos_app_ecrconfig') {
        return $cache[$table] = [];
    }
    $columns = [];
    $stmt = ecr_stmt($con, 'SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME=? ORDER BY ORDINAL_POSITION');
    $stmt->bind_param('s', $table);
    $stmt->execute();
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        $columns[] = (string)$row['COLUMN_NAME'];
    }
    $stmt->close();
    return $cache[$table] = $columns;
}

function ecr_exists(mysqli $con, int $id): bool
{
    if ($id <= 0) {
        return false;
    }
    $stmt = ecr_stmt($con, 'SELECT id FROM jos_app_ecrconfig WHERE id=? LIMIT 1');
    $stmt->bind_param('i', $id);
    $stmt->execute();
    $exists = (bool)$stmt->get_result()->fetch_assoc();
    $stmt->close();
    return $exists;
}

function ecr_fetch_row(mysqli $con, int $id): ?array
{
    $stmt = ecr_stmt($con, 'SELECT * FROM jos_app_ecrconfig WHERE id=? LIMIT 1');
    $stmt->bind_param('i', $id);
    $stmt->execute();
    $row = $stmt->get_result()->fetch_assoc() ?: null;
    $stmt->close();
    return $row;
}

function ecr_month_exists(mysqli $con, int $monthId): bool
{
    if ($monthId <= 0) {
        return false;
    }
    $stmt = ecr_stmt($con, 'SELECT id FROM jos_app_mmonth WHERE id=? LIMIT 1');
    $stmt->bind_param('i', $monthId);
    $stmt->execute();
    $exists = (bool)$stmt->get_result()->fetch_assoc();
    $stmt->close();
    return $exists;
}

function ecr_year_exists(mysqli $con, int $yearId): bool
{
    if ($yearId <= 0) {
        return false;
    }
    $stmt = ecr_stmt($con, 'SELECT id FROM jos_app_year WHERE id=? LIMIT 1');
    $stmt->bind_param('i', $yearId);
    $stmt->execute();
    $exists = (bool)$stmt->get_result()->fetch_assoc();
    $stmt->close();
    return $exists;
}

function ecr_clean_ids(array $ids): array
{
    return array_values(array_unique(array_filter(array_map('intval', $ids), static fn($id) => $id > 0)));
}

function ecr_component_ids_valid(mysqli $con, array $ids): bool
{
    $ids = ecr_clean_ids($ids);
    if (!$ids) {
        return true;
    }
    $placeholders = implode(',', array_fill(0, count($ids), '?'));
    $types = str_repeat('i', count($ids));
    $stmt = ecr_stmt($con, "SELECT COUNT(*) AS total FROM jos_app_salarycomponentmaster WHERE id IN ($placeholders)");
    $stmt->bind_param($types, ...$ids);
    $stmt->execute();
    $count = (int)($stmt->get_result()->fetch_assoc()['total'] ?? 0);
    $stmt->close();
    return $count === count($ids);
}

function ecr_decode_components($json): array
{
    $decoded = json_decode((string)$json, true);
    if (!is_array($decoded)) {
        return [];
    }
    $rows = [];
    foreach ($decoded as $field => $data) {
        $fieldName = trim((string)$field);
        if ($fieldName === '') {
            continue;
        }
        $componentCsv = is_array($data) ? (string)($data['component'] ?? '') : '';
        $rows[] = [
            'field' => $fieldName,
            'components' => ecr_clean_ids($componentCsv === '' ? [] : explode(',', $componentCsv)),
        ];
    }
    return $rows;
}

function ecr_default_component_rows(): array
{
    return [
        ['field' => 'Gross Wages', 'components' => []],
        ['field' => 'Epf Wages', 'components' => []],
        ['field' => 'Epf Contri', 'components' => []],
    ];
}

function ecr_component_json(array $rows): string
{
    $payload = [];
    foreach ($rows as $row) {
        $field = trim((string)($row['field'] ?? ''));
        if ($field === '') {
            continue;
        }
        $payload[$field] = ['component' => implode(',', ecr_clean_ids((array)($row['components'] ?? [])))];
    }
    return json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?: '{}';
}

function ecr_save_row(mysqli $con, int $id, array $data): int
{
    $columns = ecr_columns($con, 'jos_app_ecrconfig');
    $spec = ['month' => 'i', 'year' => 'i', 'components' => 's'];
    $fields = [];
    $types = '';
    $params = [];
    foreach ($spec as $field => $type) {
        if (!in_array($field, $columns, true)) {
            continue;
        }
        $fields[] = $field;
        $types .= $type;
        $params[] = $type === 'i' ? (int)$data[$field] : (string)$data[$field];
    }
    if (!$fields) {
        throw new RuntimeException('No ECR configuration fields are available.');
    }

    if ($id > 0) {
        $sets = array_map(static fn($field) => '`' . $field . '`=?', $fields);
        $stmt = ecr_stmt($con, 'UPDATE jos_app_ecrconfig SET ' . implode(',', $sets) . ' WHERE id=?');
        $types .= 'i';
        $params[] = $id;
        $stmt->bind_param($types, ...$params);
        if (!$stmt->execute()) {
            throw new RuntimeException('Unable to update ECR configuration.');
        }
        $stmt->close();
        return $id;
    }

    $stmt = ecr_stmt($con, 'INSERT INTO jos_app_ecrconfig (`' . implode('`,`', $fields) . '`) VALUES (' . implode(',', array_fill(0, count($fields), '?')) . ')');
    $stmt->bind_param($types, ...$params);
    if (!$stmt->execute()) {
        throw new RuntimeException('Unable to add ECR configuration.');
    }
    $savedId = (int)$con->insert_id;
    $stmt->close();
    return $savedId;
}

function ecr_text(array $row, string $key, string $default = ''): string
{
    return array_key_exists($key, $row) && $row[$key] !== null ? (string)$row[$key] : $default;
}

function ecr_int_row(array $row, string $key, int $default = 0): int
{
    return array_key_exists($key, $row) && $row[$key] !== null ? (int)$row[$key] : $default;
}

function ecr_component_summary($json, array $componentMap): string
{
    $lines = [];
    foreach (ecr_decode_components($json) as $row) {
        $names = [];
        foreach ($row['components'] as $componentId) {
            $names[] = $componentMap[$componentId] ?? ('#' . $componentId);
        }
        $lines[] = $row['field'] . ' : -> ' . ($names ? implode(', ', $names) : '-');
    }
    return implode("\n", $lines);
}

$months = ecr_options($con, 'SELECT id,month FROM jos_app_mmonth ORDER BY id ASC');
$years = ecr_options($con, 'SELECT id,year FROM jos_app_year ORDER BY id DESC');
$components = ecr_options($con, 'SELECT id,componentname,status,orderby FROM jos_app_salarycomponentmaster ORDER BY orderby ASC,id ASC');
$monthMap = [];
$yearMap = [];
$componentMap = [];
foreach ($months as $row) {
    $monthMap[(int)$row['id']] = (string)$row['month'];
}
foreach ($years as $row) {
    $yearMap[(int)$row['id']] = (string)$row['year'];
}
foreach ($components as $row) {
    $componentMap[(int)$row['id']] = (string)$row['componentname'];
}
$componentOptions = [];
foreach ($components as $row) {
    $componentOptions[] = ['id' => (int)$row['id'], 'name' => (string)$row['componentname']];
}

$mode = (string)($_GET['mode'] ?? '');
$isForm = $mode === 'add';
$editId = isset($_GET['edit']) ? max(0, (int)$_GET['edit']) : 0;
$editRow = ['id' => 0, 'month' => '', 'year' => '', 'components' => ecr_component_json(ecr_default_component_rows())];

if ($isForm && empty($acl['can_add'])) {
    http_response_code(403);
    exit('Access denied.');
}

if ($editId > 0) {
    if (empty($acl['can_edit'])) {
        http_response_code(403);
        exit('Access denied.');
    }
    $isForm = true;
    $editRow = ecr_fetch_row($con, $editId) ?: [];
    if (!$editRow) {
        $_SESSION['flash_ecr_configuration'] = 'ECR Configuration was not found.';
        redirect('/payroll/ecr-configuration.php');
    }
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = (string)($_POST['action'] ?? '');
    if (!verify_csrf($_POST['_csrf'] ?? null)) {
        $errors[] = 'Security token expired. Please refresh and try again.';
    } elseif ($action === 'save') {
        $id = max(0, (int)($_POST['id'] ?? 0));
        if ($id > 0 && empty($acl['can_edit'])) {
            $errors[] = 'You do not have permission to edit ECR configurations.';
        }
        if ($id === 0 && empty($acl['can_add'])) {
            $errors[] = 'You do not have permission to add ECR configurations.';
        }
        if ($id > 0 && !ecr_exists($con, $id)) {
            $errors[] = 'ECR Configuration was not found.';
        }

        $month = (int)($_POST['month'] ?? 0);
        $year = (int)($_POST['year'] ?? 0);
        $fields = (array)($_POST['field'] ?? []);
        $componentRows = [];
        $allComponentIds = [];
        foreach ($fields as $index => $field) {
            $fieldName = trim((string)$field);
            if ($fieldName === '') {
                continue;
            }
            if (strlen($fieldName) > 120) {
                $errors[] = 'ECR field names must be 120 characters or fewer.';
                continue;
            }
            $ids = ecr_clean_ids((array)($_POST['components'][$index] ?? []));
            $allComponentIds = array_merge($allComponentIds, $ids);
            $componentRows[] = ['field' => $fieldName, 'components' => $ids];
        }

        if (!$month || !ecr_month_exists($con, $month)) {
            $errors[] = 'Select a valid Month.';
        }
        if (!$year || !ecr_year_exists($con, $year)) {
            $errors[] = 'Select a valid Year.';
        }
        if (!$componentRows) {
            $errors[] = 'Add at least one ECR component field.';
        }
        if (!ecr_component_ids_valid($con, $allComponentIds)) {
            $errors[] = 'Select valid Salary Components.';
        }

        $data = [
            'month' => $month,
            'year' => $year,
            'components' => ecr_component_json($componentRows),
        ];

        if (!$errors) {
            try {
                ecr_save_row($con, $id, $data);
                $_SESSION['flash_ecr_configuration'] = $id > 0 ? 'ECR Configuration updated successfully.' : 'ECR Configuration added successfully.';
                redirect('/payroll/ecr-configuration.php');
            } catch (Throwable $e) {
                $errors[] = 'Unable to save the ECR configuration.';
            }
        }
        $isForm = true;
        $editRow = $data + ['id' => $id];
    }
}

$filterQ = trim((string)($_GET['q'] ?? ''));
$filterMonth = isset($_GET['month']) && $_GET['month'] !== '' ? (int)$_GET['month'] : 0;
$filterYear = isset($_GET['year']) && $_GET['year'] !== '' ? (int)$_GET['year'] : 0;
$page = max(1, (int)($_GET['page'] ?? 1));
$perPage = 20;
$rows = [];
$totalRows = 0;
$pages = 1;

if (!$isForm) {
    $where = ['1=1'];
    $types = '';
    $params = [];
    if ($filterQ !== '') {
        $where[] = '(e.components LIKE ? OR EXISTS (SELECT 1 FROM jos_app_salarycomponentmaster sc WHERE sc.componentname LIKE ? AND e.components REGEXP CONCAT(\'"component":"([0-9]+,)*\', sc.id, \'(,[0-9]+)*"\')))';
        $types .= 'ss';
        $params[] = '%' . $filterQ . '%';
        $params[] = '%' . $filterQ . '%';
    }
    if ($filterMonth > 0) {
        $where[] = 'e.month=?';
        $types .= 'i';
        $params[] = $filterMonth;
    }
    if ($filterYear > 0) {
        $where[] = 'e.year=?';
        $types .= 'i';
        $params[] = $filterYear;
    }
    $whereSql = implode(' AND ', $where);

    $stmt = ecr_stmt($con, 'SELECT COUNT(*) AS total FROM jos_app_ecrconfig e WHERE ' . $whereSql);
    if ($types !== '') {
        $stmt->bind_param($types, ...$params);
    }
    $stmt->execute();
    $totalRows = (int)($stmt->get_result()->fetch_assoc()['total'] ?? 0);
    $stmt->close();

    $pages = max(1, (int)ceil($totalRows / $perPage));
    $page = min($page, $pages);
    $offset = ($page - 1) * $perPage;

    $stmt = ecr_stmt($con, 'SELECT e.* FROM jos_app_ecrconfig e WHERE ' . $whereSql . ' ORDER BY e.id DESC LIMIT ? OFFSET ?');
    $listTypes = $types . 'ii';
    $listParams = $params;
    $listParams[] = $perPage;
    $listParams[] = $offset;
    $stmt->bind_param($listTypes, ...$listParams);
    $stmt->execute();
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        $rows[] = $row;
    }
    $stmt->close();
}

$value = static function (string $key, $default = '') use (&$editRow) {
    return $editRow[$key] ?? $default;
};
$componentRows = ecr_decode_components($value('components'));
if (!$componentRows) {
    $componentRows = ecr_default_component_rows();
}
$input = 'mt-1 w-full rounded-lg border border-slate-200 bg-white px-3 py-2.5 text-sm text-slate-800 outline-none focus:border-brand-500 focus:ring-2 focus:ring-brand-100';
$filterInput = 'rounded-xl border border-slate-200 px-3 py-2.5 text-sm';

console_header('ECR Configuration', $pageLink);
?>
<div class="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
  <div>
    <div class="mb-2 flex items-center gap-2 text-xs font-semibold text-slate-500"><a href="/dashboard.php">Dashboard</a><i class="fa-solid fa-chevron-right text-[9px]"></i><span>D. Masters</span><i class="fa-solid fa-chevron-right text-[9px]"></i><span>Payroll Settings</span><i class="fa-solid fa-chevron-right text-[9px]"></i><span class="text-brand-600">ECR Configuration</span></div>
    <h1 class="text-2xl font-bold text-slate-900">ECR Configuration</h1>
    <p class="mt-1 text-sm text-slate-500">Configure month-wise ECR wage and EPF contribution component mappings.</p>
  </div>
</div>
<?php if ($flash): ?><div class="mb-5 rounded-xl border border-emerald-100 bg-emerald-50 px-5 py-4 text-sm font-semibold text-emerald-700"><i class="fa-solid fa-circle-check mr-2"></i><?= h($flash) ?></div><?php endif; ?>
<?php if ($errors): ?><div class="mb-5 rounded-xl border border-red-100 bg-red-50 px-5 py-4 text-sm font-semibold text-red-700"><div class="font-bold">Please fix the following</div><ul class="mt-2 list-inside list-disc"><?php foreach ($errors as $error): ?><li><?= h($error) ?></li><?php endforeach; ?></ul></div><?php endif; ?>

<?php if ($isForm): ?>
<form method="post" class="space-y-4">
  <input type="hidden" name="_csrf" value="<?= h(csrf_token()) ?>">
  <input type="hidden" name="action" value="save">
  <input type="hidden" name="id" value="<?= (int)$value('id', 0) ?>">
  <section class="rounded-2xl border border-slate-100 bg-white p-4 shadow-sm">
    <div class="mb-4 flex flex-wrap items-center justify-between gap-3">
      <div class="flex items-center gap-3"><span class="flex h-9 w-9 items-center justify-center rounded-lg bg-brand-50 text-brand-600"><i class="fa-solid fa-file-invoice"></i></span><div><h2 class="font-bold text-slate-800"><?= (int)$value('id', 0) > 0 ? 'Edit ECR Configuration' : 'New ECR Configuration' ?></h2><p class="text-xs text-slate-400">Fields marked with * are required.</p></div></div>
      <a href="/payroll/ecr-configuration.php" class="rounded-lg border border-slate-200 bg-white px-4 py-2 text-sm font-bold text-slate-600 hover:bg-slate-50"><i class="fa-solid fa-arrow-left mr-2"></i>Back to List</a>
    </div>
    <div class="grid gap-3 md:grid-cols-2">
      <label class="text-sm font-semibold text-slate-700">Month *<select name="month" required class="<?= $input ?>"><option value="">Select Month</option><?php foreach ($months as $row): ?><option value="<?= (int)$row['id'] ?>" <?= (int)$value('month') === (int)$row['id'] ? 'selected' : '' ?>><?= h((string)$row['month']) ?></option><?php endforeach; ?></select></label>
      <label class="text-sm font-semibold text-slate-700">Year *<select name="year" required class="<?= $input ?>"><option value="">Select Year</option><?php foreach ($years as $row): ?><option value="<?= (int)$row['id'] ?>" <?= (int)$value('year') === (int)$row['id'] ? 'selected' : '' ?>><?= h((string)$row['year']) ?></option><?php endforeach; ?></select></label>
    </div>
    <div class="mt-5 overflow-hidden rounded-xl border border-slate-100">
      <div class="flex items-center justify-between gap-3 border-b border-slate-100 bg-slate-50 px-4 py-3"><div><h3 class="text-sm font-bold text-slate-800">ECR Component Mapping</h3><p class="mt-0.5 text-xs font-medium text-slate-400">Map each ECR wage field to one or more salary components.</p></div><button type="button" id="add-ecr-row" class="rounded-lg border border-slate-200 bg-white px-3 py-2 text-xs font-bold text-slate-600 hover:bg-brand-50 hover:text-brand-700"><i class="fa-solid fa-plus mr-1"></i>Add Row</button></div>
      <div id="ecr-rows" class="divide-y divide-slate-100">
        <?php foreach ($componentRows as $index => $row): ?>
        <div class="grid gap-3 p-4 md:grid-cols-[280px_1fr_48px] ecr-row">
          <label class="text-sm font-semibold text-slate-700">Field<input name="field[]" value="<?= h($row['field']) ?>" maxlength="120" required class="<?= $input ?>"></label>
          <div class="text-sm font-semibold text-slate-700">Component
            <div class="relative mt-1 js-ecr-component-picker" data-name="components[<?= (int)$index ?>][]" data-placeholder="Type or select component name" data-heading="-Select Component Name-" data-empty="No components found" data-options='<?= h(json_encode($componentOptions, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) ?>' data-selected='<?= h(json_encode($row['components'])) ?>'>
              <div class="js-picker-control min-h-[46px] w-full rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm text-slate-800 outline-none focus-within:border-brand-500 focus-within:ring-2 focus-within:ring-brand-100">
                <div class="js-picker-tags mb-1 flex flex-wrap gap-1.5"></div>
                <input type="text" class="js-picker-search w-full border-0 bg-transparent p-0 text-sm font-medium text-slate-800 outline-none placeholder:text-slate-400" placeholder="Type or select component name" autocomplete="off">
              </div>
              <div class="js-picker-dropdown hidden absolute left-0 right-0 top-full z-40 max-h-72 overflow-y-auto border border-slate-300 bg-white shadow-xl"></div>
              <div class="js-picker-inputs"></div>
            </div>
          </div>
          <div class="flex items-end"><button type="button" class="remove-ecr-row h-[46px] w-[46px] rounded-lg border border-slate-200 text-slate-500 hover:border-red-100 hover:bg-red-50 hover:text-red-600" title="Remove row"><i class="fa-solid fa-trash"></i></button></div>
        </div>
        <?php endforeach; ?>
      </div>
    </div>
  </section>
  <div class="flex flex-wrap justify-end gap-2"><a href="/payroll/ecr-configuration.php" class="rounded-lg border border-slate-200 bg-white px-5 py-2.5 text-sm font-bold text-slate-600">Cancel</a><button class="rounded-lg bg-brand-600 px-5 py-2.5 text-sm font-bold text-white hover:bg-brand-700"><i class="fa-solid fa-floppy-disk mr-2"></i>Save Configuration</button></div>
</form>
<?php else: ?>
<section class="overflow-hidden rounded-2xl border border-slate-100 bg-white shadow-sm">
  <div class="flex flex-col gap-3 border-b border-slate-100 px-5 py-4 sm:flex-row sm:items-center sm:justify-between"><div><h2 class="font-bold text-slate-800">ECR Configuration List</h2><p class="mt-1 text-xs font-medium text-slate-400">ECR component mappings are ordered by latest record.</p></div><?php if (!empty($acl['can_add'])): ?><a href="?mode=add" class="inline-flex items-center justify-center gap-2 rounded-lg bg-brand-600 px-4 py-2.5 text-sm font-bold text-white shadow-sm hover:bg-brand-700"><i class="fa-solid fa-plus"></i>+ Add</a><?php endif; ?></div>
  <form method="get" class="grid gap-3 border-b border-slate-100 p-5 md:grid-cols-2 xl:grid-cols-5"><input name="q" value="<?= h($filterQ) ?>" class="<?= $filterInput ?>" placeholder="Search field or component"><select name="month" class="<?= $filterInput ?>"><option value="">All Months</option><?php foreach ($months as $row): ?><option value="<?= (int)$row['id'] ?>" <?= $filterMonth === (int)$row['id'] ? 'selected' : '' ?>><?= h((string)$row['month']) ?></option><?php endforeach; ?></select><select name="year" class="<?= $filterInput ?>"><option value="">All Years</option><?php foreach ($years as $row): ?><option value="<?= (int)$row['id'] ?>" <?= $filterYear === (int)$row['id'] ? 'selected' : '' ?>><?= h((string)$row['year']) ?></option><?php endforeach; ?></select><div class="flex gap-2 xl:col-span-2"><button class="rounded-xl bg-slate-900 px-5 py-2.5 text-sm font-bold text-white"><i class="fa-solid fa-filter mr-2"></i>Filter</button><a href="/payroll/ecr-configuration.php" class="rounded-xl border border-slate-200 px-5 py-2.5 text-sm font-bold text-slate-600">Clear</a></div></form>
  <div class="overflow-x-auto"><table class="w-full min-w-[920px] text-left text-sm"><thead class="bg-slate-50 text-[10px] font-extrabold uppercase tracking-wider text-slate-700"><tr><th class="px-5 py-4 w-20">Sr No</th><th class="px-5 py-4">Month</th><th class="px-5 py-4">Year</th><th class="px-5 py-4">Component Name</th><th class="px-5 py-4 text-right">Actions</th></tr></thead><tbody class="divide-y divide-slate-100">
    <?php if (!$rows): ?><tr><td colspan="5" class="px-6 py-14 text-center font-semibold text-slate-400">No ECR configurations found.</td></tr><?php endif; ?>
    <?php foreach ($rows as $index => $row): ?><tr class="align-top hover:bg-slate-50/70"><td class="px-5 py-4 font-semibold text-slate-500"><?= (($page - 1) * $perPage) + $index + 1 ?></td><td class="px-5 py-4 font-bold text-slate-800"><?= h($monthMap[ecr_int_row($row, 'month')] ?? ('#' . ecr_int_row($row, 'month'))) ?></td><td class="px-5 py-4"><?= h($yearMap[ecr_int_row($row, 'year')] ?? ('#' . ecr_int_row($row, 'year'))) ?></td><td class="px-5 py-4 whitespace-pre-line text-slate-700"><?= h(ecr_component_summary(ecr_text($row, 'components'), $componentMap)) ?></td><td class="px-5 py-4"><div class="flex justify-end gap-2"><?php if (!empty($acl['can_edit'])): ?><a href="?edit=<?= ecr_int_row($row, 'id') ?>" class="rounded-lg border border-slate-200 px-3 py-2 text-slate-600 hover:bg-brand-50 hover:text-brand-600" title="Edit"><i class="fa-solid fa-pen"></i></a><?php endif; ?></div></td></tr><?php endforeach; ?>
  </tbody></table></div>
  <?php if ($totalRows > $perPage): ?><div class="flex items-center justify-between border-t border-slate-100 px-5 py-4 text-sm"><span class="font-medium text-slate-500"><?= $totalRows ?> configurations</span><div class="flex gap-2"><?php $base = ['q' => $filterQ, 'month' => $filterMonth ?: '', 'year' => $filterYear ?: '']; if ($page > 1): ?><a class="rounded-lg border border-slate-200 px-4 py-2 font-semibold" href="?<?= h(http_build_query($base + ['page' => $page - 1])) ?>">Previous</a><?php endif; ?><?php if ($page < $pages): ?><a class="rounded-lg border border-slate-200 px-4 py-2 font-semibold" href="?<?= h(http_build_query($base + ['page' => $page + 1])) ?>">Next</a><?php endif; ?></div></div><?php endif; ?>
</section>
<?php endif; ?>
<?php if ($isForm): ?>
<template id="ecr-row-template">
  <div class="grid gap-3 p-4 md:grid-cols-[280px_1fr_48px] ecr-row">
    <label class="text-sm font-semibold text-slate-700">Field<input name="field[]" value="" maxlength="120" required class="<?= $input ?>"></label>
    <div class="text-sm font-semibold text-slate-700">Component
      <div class="relative mt-1 js-ecr-component-picker" data-name="" data-placeholder="Type or select component name" data-heading="-Select Component Name-" data-empty="No components found" data-options='<?= h(json_encode($componentOptions, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)) ?>' data-selected='[]'>
        <div class="js-picker-control min-h-[46px] w-full rounded-lg border border-slate-200 bg-white px-3 py-2 text-sm text-slate-800 outline-none focus-within:border-brand-500 focus-within:ring-2 focus-within:ring-brand-100">
          <div class="js-picker-tags mb-1 flex flex-wrap gap-1.5"></div>
          <input type="text" class="js-picker-search w-full border-0 bg-transparent p-0 text-sm font-medium text-slate-800 outline-none placeholder:text-slate-400" placeholder="Type or select component name" autocomplete="off">
        </div>
        <div class="js-picker-dropdown hidden absolute left-0 right-0 top-full z-40 max-h-72 overflow-y-auto border border-slate-300 bg-white shadow-xl"></div>
        <div class="js-picker-inputs"></div>
      </div>
    </div>
    <div class="flex items-end"><button type="button" class="remove-ecr-row h-[46px] w-[46px] rounded-lg border border-slate-200 text-slate-500 hover:border-red-100 hover:bg-red-50 hover:text-red-600" title="Remove row"><i class="fa-solid fa-trash"></i></button></div>
  </div>
</template>
<script>
function initEcrPicker(picker) {
  if (picker.dataset.ready === '1') return;
  picker.dataset.ready = '1';
  const options = JSON.parse(picker.dataset.options || '[]');
  const fieldName = picker.dataset.name || 'components[]';
  const placeholderText = picker.dataset.placeholder || 'Type or select component name';
  const headingText = picker.dataset.heading || '-Select Component Name-';
  const emptyText = picker.dataset.empty || 'No components found';
  let selected = JSON.parse(picker.dataset.selected || '[]').map(Number);
  const control = picker.querySelector('.js-picker-control');
  const search = picker.querySelector('.js-picker-search');
  const tags = picker.querySelector('.js-picker-tags');
  const dropdown = picker.querySelector('.js-picker-dropdown');
  const inputs = picker.querySelector('.js-picker-inputs');

  function labelFor(id) {
    const option = options.find(function (item) { return Number(item.id) === Number(id); });
    return option ? option.name : '#' + id;
  }
  function syncInputs() {
    inputs.innerHTML = '';
    selected.forEach(function (id) {
      const input = document.createElement('input');
      input.type = 'hidden';
      input.name = fieldName;
      input.value = String(id);
      inputs.appendChild(input);
    });
  }
  function drawTags() {
    tags.innerHTML = '';
    if (!selected.length) {
      tags.classList.add('hidden');
      search.placeholder = placeholderText;
    } else {
      tags.classList.remove('hidden');
      search.placeholder = '';
    }
    selected.forEach(function (id) {
      const tag = document.createElement('span');
      tag.className = 'inline-flex items-center gap-1 rounded-md bg-brand-50 px-2 py-1 text-xs font-bold text-brand-700';
      tag.textContent = labelFor(id);
      const remove = document.createElement('button');
      remove.type = 'button';
      remove.className = 'ml-1 text-brand-500 hover:text-red-600';
      remove.innerHTML = '&times;';
      remove.addEventListener('click', function () {
        selected = selected.filter(function (value) { return Number(value) !== Number(id); });
        render();
        openDropdown();
        search.focus();
      });
      tag.appendChild(remove);
      tags.appendChild(tag);
    });
  }
  function drawOptions() {
    const term = search.value.trim().toLowerCase();
    dropdown.innerHTML = '';
    const placeholder = document.createElement('button');
    placeholder.type = 'button';
    placeholder.className = 'block w-full bg-brand-600 px-3 py-2 text-left text-sm font-semibold text-white';
    placeholder.textContent = headingText;
    placeholder.addEventListener('click', function () {
      search.value = '';
      drawOptions();
      search.focus();
    });
    dropdown.appendChild(placeholder);
    const available = options.filter(function (option) {
      return !selected.includes(Number(option.id)) && (!term || option.name.toLowerCase().includes(term));
    });
    if (!available.length) {
      const empty = document.createElement('div');
      empty.className = 'px-3 py-3 text-sm font-medium text-slate-400';
      empty.textContent = emptyText;
      dropdown.appendChild(empty);
      return;
    }
    available.forEach(function (option) {
      const item = document.createElement('button');
      item.type = 'button';
      item.className = 'block w-full px-3 py-2 text-left text-sm font-medium text-slate-700 hover:bg-brand-50 hover:text-brand-700';
      item.textContent = option.name;
      item.addEventListener('click', function () {
        selected.push(Number(option.id));
        search.value = '';
        render();
        openDropdown();
        search.focus();
      });
      dropdown.appendChild(item);
    });
  }
  function openDropdown() {
    drawOptions();
    dropdown.classList.remove('hidden');
  }
  function render() {
    drawTags();
    syncInputs();
    drawOptions();
  }
  control.addEventListener('click', function () {
    search.focus();
    openDropdown();
  });
  search.addEventListener('focus', openDropdown);
  search.addEventListener('input', openDropdown);
  search.addEventListener('keydown', function (event) {
    if (event.key === 'Escape') dropdown.classList.add('hidden');
  });
  document.addEventListener('click', function (event) {
    if (!picker.contains(event.target)) dropdown.classList.add('hidden');
  });
  render();
}
function reindexEcrRows() {
  document.querySelectorAll('#ecr-rows .js-ecr-component-picker').forEach(function (picker, index) {
    picker.dataset.name = 'components[' + index + '][]';
    if (picker.dataset.ready !== '1') initEcrPicker(picker);
  });
}
document.querySelectorAll('.js-ecr-component-picker').forEach(initEcrPicker);
document.getElementById('add-ecr-row')?.addEventListener('click', function () {
  const template = document.getElementById('ecr-row-template');
  const clone = template.content.cloneNode(true);
  document.getElementById('ecr-rows').appendChild(clone);
  reindexEcrRows();
});
document.addEventListener('click', function (event) {
  const button = event.target.closest('.remove-ecr-row');
  if (!button) return;
  const rows = document.querySelectorAll('#ecr-rows .ecr-row');
  if (rows.length <= 1) return;
  button.closest('.ecr-row')?.remove();
  reindexEcrRows();
});
reindexEcrRows();
</script>
<?php endif; ?>
<?php console_footer(); ?>
