<?php
declare(strict_types=1);

require_once dirname(__DIR__) . '/includes/layout.php';
require_once dirname(__DIR__) . '/includes/report-data.php';
require_once __DIR__ . '/_master_config.php';

if (!isset($crmMasterKey) || !is_string($crmMasterKey)) {
    throw new RuntimeException('CRM master configuration is missing.');
}

$definition = crm_master_definition($crmMasterKey);
$db = crm_report_db();
if (!$db) {
    throw new RuntimeException('ABOX database connection is unavailable.');
}

$table = $definition['table'];
$nameColumn = $definition['name_column'];
$orderColumn = $definition['order_column'] ?? null;
$stateColumn = $definition['state_column'] ?? null;

if (!crm_report_table($db, $table)) {
    throw new RuntimeException("Required CRM table {$table} is unavailable.");
}

function crm_master_redirect(string $message, string $type = 'success'): void
{
    $_SESSION['crm_master_flash'] = ['message' => $message, 'type' => $type];
    $path = (string)(parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?: '');
    header('Location: ' . $path);
    exit;
}

function crm_master_usage(mysqli $db, array $definition, int $id): array
{
    $usage = [];
    foreach ($definition['references'] as $reference) {
        if (!crm_report_table($db, $reference['table'])) {
            continue;
        }
        $sql = "SELECT COUNT(*) AS total FROM `{$reference['table']}` WHERE `{$reference['column']}` = ?";
        $statement = $db->prepare($sql);
        if (!$statement) {
            throw new RuntimeException($db->error ?: 'Unable to inspect master usage.');
        }
        $statement->bind_param('i', $id);
        $statement->execute();
        $row = $statement->get_result()->fetch_assoc();
        $count = (int)($row['total'] ?? 0);
        if ($count > 0) {
            $usage[] = $count . ' ' . $reference['label'];
        }
    }
    return $usage;
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $token = (string)($_POST['csrf_token'] ?? '');
    if ($token === '' || !hash_equals(crm_csrf_token(), $token)) {
        crm_master_redirect('Your session token expired. Please try again.', 'error');
    }

    $action = (string)($_POST['action'] ?? 'save');
    $id = filter_var($_POST['id'] ?? 0, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) ?: 0;

    try {
        if ($action === 'delete') {
            if ($id < 1) {
                throw new RuntimeException('Invalid master record.');
            }
            $usage = crm_master_usage($db, $definition, $id);
            if ($usage !== []) {
                throw new RuntimeException('Delete blocked: this record is used by ' . implode(' and ', $usage) . '.');
            }
            $statement = $db->prepare("DELETE FROM `{$table}` WHERE `id` = ?");
            $statement->bind_param('i', $id);
            $statement->execute();
            crm_master_redirect($definition['singular'] . ' deleted safely.');
        }

        $name = trim((string)($_POST['name'] ?? ''));
        if ($name === '' || mb_strlen($name) > 150) {
            throw new RuntimeException($definition['name_label'] . ' is required and must be 150 characters or fewer.');
        }
        $ordering = filter_var($_POST['ordering'] ?? 0, FILTER_VALIDATE_INT);
        if ($orderColumn !== null && ($ordering === false || $ordering < 0 || $ordering > 99999)) {
            throw new RuntimeException('Order must be a whole number between 0 and 99999.');
        }
        $state = (int)($_POST['state'] ?? 1);
        if ($stateColumn !== null && !in_array($state, [1, 0, 2, -2], true)) {
            throw new RuntimeException('Invalid publication state.');
        }

        $duplicate = $db->prepare(
            "SELECT `id` FROM `{$table}` WHERE LOWER(TRIM(`{$nameColumn}`)) = LOWER(TRIM(?)) AND `id` <> ? LIMIT 1"
        );
        $duplicate->bind_param('si', $name, $id);
        $duplicate->execute();
        if ($duplicate->get_result()->fetch_assoc()) {
            throw new RuntimeException($definition['singular'] . ' already exists.');
        }

        if ($id > 0) {
            $fields = ["`{$nameColumn}` = ?"];
            $types = 's';
            $values = [$name];
            if ($orderColumn !== null) {
                $fields[] = "`{$orderColumn}` = ?";
                $types .= 'i';
                $values[] = (int)$ordering;
            }
            if ($stateColumn !== null) {
                $fields[] = "`{$stateColumn}` = ?";
                $types .= 'i';
                $values[] = $state;
            }
            $types .= 'i';
            $values[] = $id;
            $statement = $db->prepare("UPDATE `{$table}` SET " . implode(', ', $fields) . ' WHERE `id` = ?');
            $statement->bind_param($types, ...$values);
            $statement->execute();
            crm_master_redirect($definition['singular'] . ' updated successfully.');
        }

        $columns = ["`{$nameColumn}`"];
        $placeholders = ['?'];
        $types = 's';
        $values = [$name];
        if ($orderColumn !== null) {
            $columns[] = "`{$orderColumn}`";
            $placeholders[] = '?';
            $types .= 'i';
            $values[] = (int)$ordering;
        }
        if ($stateColumn !== null) {
            $columns[] = "`{$stateColumn}`";
            $placeholders[] = '?';
            $types .= 'i';
            $values[] = $state;
        }
        $statement = $db->prepare(
            "INSERT INTO `{$table}` (" . implode(', ', $columns) . ') VALUES (' . implode(', ', $placeholders) . ')'
        );
        $statement->bind_param($types, ...$values);
        $statement->execute();
        crm_master_redirect($definition['singular'] . ' added successfully.');
    } catch (Throwable $exception) {
        $_SESSION['crm_master_old'] = $_POST;
        crm_master_redirect($exception->getMessage(), 'error');
    }
}

$flash = $_SESSION['crm_master_flash'] ?? null;
unset($_SESSION['crm_master_flash']);
$old = $_SESSION['crm_master_old'] ?? [];
unset($_SESSION['crm_master_old']);

$editId = filter_var($_GET['edit'] ?? 0, FILTER_VALIDATE_INT, ['options' => ['min_range' => 1]]) ?: 0;
$editing = null;
if ($editId > 0) {
    $statement = $db->prepare("SELECT * FROM `{$table}` WHERE `id` = ? LIMIT 1");
    $statement->bind_param('i', $editId);
    $statement->execute();
    $editing = $statement->get_result()->fetch_assoc() ?: null;
}

$search = trim((string)($_GET['q'] ?? ''));
$sql = "SELECT * FROM `{$table}`";
$statement = null;
if ($search !== '') {
    $sql .= " WHERE `{$nameColumn}` LIKE ?";
}
$sql .= $orderColumn !== null
    ? " ORDER BY `{$orderColumn}` ASC, `id` DESC LIMIT 500"
    : " ORDER BY `{$nameColumn}` ASC, `id` DESC LIMIT 500";
$statement = $db->prepare($sql);
if ($search !== '') {
    $like = '%' . $search . '%';
    $statement->bind_param('s', $like);
}
$statement->execute();
$records = $statement->get_result()->fetch_all(MYSQLI_ASSOC);

crm_page_start($definition['title'], 'masters', $definition['description']);
?>
<?php if (is_array($flash)): ?>
    <div class="master-alert <?= $flash['type'] === 'error' ? 'error' : 'success' ?>" role="alert">
        <i class="fa-solid <?= $flash['type'] === 'error' ? 'fa-circle-exclamation' : 'fa-circle-check' ?>"></i>
        <?= crm_e((string)$flash['message']) ?>
    </div>
<?php endif; ?>

<div class="master-workspace">
    <section class="card master-form-card">
        <div class="card-head">
            <div class="card-title">
                <i class="fa-solid <?= crm_e($definition['icon']) ?>"></i>
                <div>
                    <h2><?= $editing ? 'Edit ' : 'New ' ?><?= crm_e($definition['singular']) ?></h2>
                    <p><?= $editing ? 'Update the selected master record' : 'Create a new master record' ?></p>
                </div>
            </div>
        </div>
        <form method="post" class="card-body" autocomplete="off">
            <input type="hidden" name="csrf_token" value="<?= crm_e(crm_csrf_token()) ?>">
            <input type="hidden" name="action" value="save">
            <input type="hidden" name="id" value="<?= (int)($editing['id'] ?? 0) ?>">
            <div class="master-form-fields">
                <div class="field full">
                    <label for="master-name"><?= crm_e($definition['name_label']) ?> <span class="required">*</span></label>
                    <input class="control" id="master-name" name="name" maxlength="150" required
                           value="<?= crm_e((string)($old['name'] ?? $editing[$nameColumn] ?? '')) ?>"
                           placeholder="Enter <?= crm_e(strtolower($definition['name_label'])) ?>">
                </div>
                <?php if ($orderColumn !== null): ?>
                    <div class="field full">
                        <label for="master-order">Order By</label>
                        <input class="control" id="master-order" name="ordering" type="number" min="0" max="99999"
                               value="<?= crm_e((string)($old['ordering'] ?? $editing[$orderColumn] ?? 0)) ?>">
                    </div>
                <?php endif; ?>
                <?php if ($stateColumn !== null): ?>
                    <div class="field full">
                        <label for="master-state">Status</label>
                        <?php $selectedState = (int)($old['state'] ?? $editing[$stateColumn] ?? 1); ?>
                        <select class="control" id="master-state" name="state">
                            <option value="1" <?= $selectedState === 1 ? 'selected' : '' ?>>Published</option>
                            <option value="0" <?= $selectedState === 0 ? 'selected' : '' ?>>Unpublished</option>
                            <option value="2" <?= $selectedState === 2 ? 'selected' : '' ?>>Archived</option>
                            <option value="-2" <?= $selectedState === -2 ? 'selected' : '' ?>>Trashed</option>
                        </select>
                    </div>
                <?php endif; ?>
            </div>
            <div class="master-form-actions">
                <button class="button primary" type="submit"><i class="fa-solid fa-floppy-disk"></i> <?= $editing ? 'Update' : 'Save' ?></button>
                <?php if ($editing): ?>
                    <a class="button secondary" href="<?= crm_e((string)(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ?: '')) ?>">Cancel</a>
                <?php endif; ?>
            </div>
        </form>
    </section>

    <section class="card master-list-card">
        <div class="card-head">
            <div class="card-title">
                <i class="fa-solid fa-list"></i>
                <div>
                    <h2><?= crm_e($definition['singular']) ?> List</h2>
                    <p><?= count($records) ?> record<?= count($records) === 1 ? '' : 's' ?> shown</p>
                </div>
            </div>
            <form method="get" class="master-search">
                <i class="fa-solid fa-magnifying-glass"></i>
                <input name="q" value="<?= crm_e($search) ?>" placeholder="Search records" aria-label="Search records">
                <?php if ($search !== ''): ?><a href="<?= crm_e((string)(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ?: '')) ?>" aria-label="Clear search"><i class="fa-solid fa-xmark"></i></a><?php endif; ?>
            </form>
        </div>
        <div class="table-wrap">
            <table class="data-table master-table">
                <thead><tr>
                    <th>ID</th>
                    <th><?= crm_e($definition['name_label']) ?></th>
                    <?php if ($orderColumn !== null): ?><th>Order</th><?php endif; ?>
                    <?php if ($stateColumn !== null): ?><th>Status</th><?php endif; ?>
                    <th>In Use</th>
                    <th>Action</th>
                </tr></thead>
                <tbody>
                <?php if ($records === []): ?>
                    <tr class="empty-row"><td colspan="6">No matching records found.</td></tr>
                <?php endif; ?>
                <?php foreach ($records as $record): ?>
                    <?php $usage = crm_master_usage($db, $definition, (int)$record['id']); ?>
                    <tr>
                        <td>#<?= (int)$record['id'] ?></td>
                        <td><strong><?= crm_e((string)$record[$nameColumn]) ?></strong></td>
                        <?php if ($orderColumn !== null): ?><td><?= (int)$record[$orderColumn] ?></td><?php endif; ?>
                        <?php if ($stateColumn !== null): ?>
                            <?php $states = [1 => ['Published', 'green'], 0 => ['Unpublished', 'amber'], 2 => ['Archived', 'blue'], -2 => ['Trashed', 'red']]; $stateInfo = $states[(int)$record[$stateColumn]] ?? ['Unknown', 'amber']; ?>
                            <td><span class="badge <?= $stateInfo[1] ?>"><?= crm_e($stateInfo[0]) ?></span></td>
                        <?php endif; ?>
                        <td><?= $usage === [] ? '<span class="master-unused">Unused</span>' : crm_e(implode(', ', $usage)) ?></td>
                        <td>
                            <div class="inline-actions">
                                <a class="button secondary small" href="?edit=<?= (int)$record['id'] ?>"><i class="fa-solid fa-pen"></i> Edit</a>
                                <form method="post" onsubmit="return confirm('Delete this unused <?= crm_e(strtolower($definition['singular'])) ?>?');">
                                    <input type="hidden" name="csrf_token" value="<?= crm_e(crm_csrf_token()) ?>">
                                    <input type="hidden" name="action" value="delete">
                                    <input type="hidden" name="id" value="<?= (int)$record['id'] ?>">
                                    <button class="button danger small" type="submit" <?= $usage !== [] ? 'disabled title="Cannot delete a record that is in use"' : '' ?>><i class="fa-solid fa-trash"></i></button>
                                </form>
                            </div>
                        </td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    </section>
</div>
<?php crm_page_end(); ?>
