<?php
/**
 * Master data: Clients (e.g. "Blue Central Healthcare")
 * Belongs to a Vertical. Has 1:1 client_branding row.
 */
require_once __DIR__ . '/../includes/config.php';
$user = require_login('internal');

$pdo    = db();
$action = $_GET['action'] ?? $_POST['action'] ?? 'list';
$id     = (int) ($_GET['id'] ?? $_POST['id'] ?? 0);
$isSysadmin = user_has_role((int) $user['id'], 'sysadmin');

// Cross-vertical "Merge verticals" (Option A) is DISABLED — this system uses SEPARATE per-vertical copies (Option B,
// 2026-06-21) maintained via admin/clone-tree.php. The button is hidden and the handlers are guarded so a stale URL
// can't trigger a merge. Flip to true to restore Option A. See [[cross-vertical-cpfp-foundation]].
$crossMergeEnabled = false;

/* ---------------------------------------------------------- POST */
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    csrf_check_or_die();

    // Write-guard: the page opens on the READ permission (client.view), but every mutation below — create / edit /
    // archive / merge — requires the WRITE permission client.manage (SysAdmin always). Viewers/auditors can browse
    // but not change client master data. (Cross-vertical merge additionally requires SysAdmin, enforced in-handler.)
    if (!$isSysadmin && !can('client.manage')) {
        flash('error', 'You do not have permission to modify clients.');
        redirect('/admin/clients.php');
    }

    if ($action === 'save') {
        $data = [
            'vertical_id'   => (int) input('vertical_id'),
            'name'          => trim((string) input('name')),
            'code'          => strtoupper(trim((string) input('code'))),
            'spoc_name'     => trim((string) input('spoc_name')) ?: null,
            'spoc_email'    => trim((string) input('spoc_email')) ?: null,
            'spoc_phone'    => trim((string) input('spoc_phone')) ?: null,
            'sla_notes'     => trim((string) input('sla_notes')) ?: null,
            'timezone'      => trim((string) input('timezone')) ?: 'Asia/Kolkata',
            'status'        => in_array(input('status'), ['active','inactive'], true) ? input('status') : 'active',
        ];
        $branding = [
            'primary_color'             => trim((string) input('primary_color')) ?: '#206bc4',
            'login_slug'                => strtolower(preg_replace('/[^a-z0-9-]/', '-', trim((string) input('login_slug')))),
            'login_message'             => trim((string) input('login_message')) ?: null,
            'show_historical_to_client' => input('show_historical_to_client') ? 1 : 0,
            'allow_client_upload'       => input('allow_client_upload')       ? 1 : 0,
            'allow_raw_data'            => input('allow_raw_data')            ? 1 : 0,
        ];

        $errors = [];
        if (!$data['vertical_id'])                  $errors[] = 'Vertical is required.';
        if ($data['name'] === '')                   $errors[] = 'Name is required.';
        if (!preg_match('/^[A-Z0-9_-]{2,50}$/', $data['code'])) $errors[] = 'Code must be 2-50 chars: A-Z 0-9 _ -';
        if ($data['spoc_email'] && !filter_var($data['spoc_email'], FILTER_VALIDATE_EMAIL)) $errors[] = 'SPOC email is not valid.';
        if (!preg_match('/^[a-z0-9-]{3,80}$/', $branding['login_slug'])) $errors[] = 'Login slug must be 3-80 chars: a-z 0-9 -';

        if (!$errors) {
            $dup = $pdo->prepare('SELECT id FROM clients WHERE code=? AND id<>? AND deleted_at IS NULL');
            $dup->execute([$data['code'], $id]);
            if ($dup->fetch()) $errors[] = 'A client with that code already exists.';

            // One client per NAME within a vertical — extra locations/processes go UNDER that client, not as
            // a new duplicate client (use "Merge" on the Clients list to consolidate any existing duplicates).
            $dupName = $pdo->prepare('SELECT id FROM clients WHERE vertical_id=? AND LOWER(name)=LOWER(?) AND id<>? AND deleted_at IS NULL');
            $dupName->execute([$data['vertical_id'], $data['name'], $id]);
            if ($dupName->fetch()) $errors[] = 'A client named "' . $data['name'] . '" already exists in this vertical. Add a Process to that client instead of creating a duplicate.';

            $dupSlug = $pdo->prepare(
                'SELECT cb.client_id FROM client_branding cb WHERE cb.login_slug=? AND cb.client_id <> ?'
            );
            $dupSlug->execute([$branding['login_slug'], $id]);
            if ($dupSlug->fetch()) $errors[] = 'That login slug is already in use by another client.';

            // A code / name can ALSO be reserved by an ARCHIVED client (uq_clients_code covers soft-deleted rows),
            // which would otherwise make the INSERT/UPDATE 500. Catch it here and point the user to Restore.
            $archCode = $pdo->prepare('SELECT name FROM clients WHERE code=? AND id<>? AND deleted_at IS NOT NULL LIMIT 1');
            $archCode->execute([$data['code'], $id]);
            if ($an = $archCode->fetchColumn()) $errors[] = 'Code "' . $data['code'] . '" belongs to an ARCHIVED client ("' . $an . '"). Restore it from “Show archived”, or choose a different code.';
            $archName = $pdo->prepare('SELECT id FROM clients WHERE vertical_id=? AND LOWER(name)=LOWER(?) AND id<>? AND deleted_at IS NOT NULL LIMIT 1');
            $archName->execute([$data['vertical_id'], $data['name'], $id]);
            if ($archName->fetchColumn()) $errors[] = 'An ARCHIVED client named "' . $data['name'] . '" exists in this vertical — restore it from “Show archived” instead of creating a duplicate.';
        }

        if ($errors) {
            foreach ($errors as $e) flash('error', $e);
            redirect('/admin/clients.php?action=' . ($id ? 'edit&id=' . $id : 'new'));
        }

      try {
        if ($id) {
            $before = $pdo->query("SELECT * FROM clients WHERE id=$id")->fetch();
            $pdo->prepare(
                'UPDATE clients
                 SET vertical_id=?, name=?, code=?, spoc_name=?, spoc_email=?, spoc_phone=?,
                     sla_notes=?, timezone=?, status=?, updated_at=NOW()
                 WHERE id=?'
            )->execute([
                $data['vertical_id'], $data['name'], $data['code'],
                $data['spoc_name'], $data['spoc_email'], $data['spoc_phone'],
                $data['sla_notes'], $data['timezone'], $data['status'], $id,
            ]);
            $clientId = $id;
            audit_log('client.update', 'client', $clientId, $before, $data);
            flash('success', 'Client updated.');
        } else {
            $pdo->prepare(
                'INSERT INTO clients
                    (vertical_id, name, code, spoc_name, spoc_email, spoc_phone, sla_notes, timezone, status, created_at, updated_at)
                 VALUES (?,?,?,?,?,?,?,?,?,NOW(),NOW())'
            )->execute([
                $data['vertical_id'], $data['name'], $data['code'],
                $data['spoc_name'], $data['spoc_email'], $data['spoc_phone'],
                $data['sla_notes'], $data['timezone'], $data['status'],
            ]);
            $clientId = (int) $pdo->lastInsertId();
            audit_log('client.create', 'client', $clientId, null, $data);
            flash('success', 'Client created.');
        }

        // Upsert branding
        $pdo->prepare(
            'INSERT INTO client_branding
                (client_id, primary_color, login_slug, login_message,
                 show_historical_to_client, allow_client_upload, allow_raw_data, updated_by, updated_at)
             VALUES (?,?,?,?,?,?,?,?,NOW())
             ON DUPLICATE KEY UPDATE
                primary_color=VALUES(primary_color),
                login_slug=VALUES(login_slug),
                login_message=VALUES(login_message),
                show_historical_to_client=VALUES(show_historical_to_client),
                allow_client_upload=VALUES(allow_client_upload),
                allow_raw_data=VALUES(allow_raw_data),
                updated_by=VALUES(updated_by),
                updated_at=NOW()'
        )->execute([
            $clientId,
            $branding['primary_color'], $branding['login_slug'], $branding['login_message'],
            $branding['show_historical_to_client'], $branding['allow_client_upload'], $branding['allow_raw_data'],
            $user['id'],
        ]);
      } catch (PDOException $e) {
        flash('error', (($e->getCode() ?? '') === '23000')
            ? 'Could not save — a code, name or login slug is already in use (it may belong to an ARCHIVED client; restore it from “Show archived”, or use different values).'
            : 'Could not save the client: ' . (defined('APP_DEBUG') && APP_DEBUG ? $e->getMessage() : 'server error'));
        redirect('/admin/clients.php?action=' . ($id ? 'edit&id=' . $id : 'new'));
      }

        redirect('/admin/clients.php');
    }

    if ($action === 'restore' && $id) {
        $c = $pdo->prepare("SELECT code,name,vertical_id FROM clients WHERE id=? AND deleted_at IS NOT NULL");
        $c->execute([$id]); $c = $c->fetch();
        if (!$c) { flash('error', 'Archived client not found (it may already be active).'); redirect('/admin/clients.php?archived=1'); }
        // Block restore if a LIVE client now holds that code or (vertical, name) — the user must rename the live one first.
        $cf = $pdo->prepare("SELECT name FROM clients WHERE deleted_at IS NULL AND (code=? OR (vertical_id=? AND LOWER(name)=LOWER(?))) LIMIT 1");
        $cf->execute([$c['code'], $c['vertical_id'], $c['name']]);
        if ($live = $cf->fetchColumn()) { flash('error', 'Cannot restore — a live client ("' . $live . '") already uses that code or name. Rename the live one first.'); redirect('/admin/clients.php?archived=1'); }
        $pdo->prepare("UPDATE clients SET deleted_at=NULL, status='active', updated_at=NOW() WHERE id=?")->execute([$id]);
        audit_log('client.restore', 'client', $id, null, ['code' => $c['code'], 'name' => $c['name']]);
        flash('success', 'Client "' . $c['name'] . '" restored. Note: if it was merged into another client, its processes/data moved there — this restores an empty shell.');
        redirect('/admin/clients.php');
    }

    if ($action === 'delete' && $id) {
        $pdo->prepare('UPDATE clients SET deleted_at=NOW(), status=? WHERE id=?')->execute(['inactive', $id]);
        audit_log('client.delete', 'client', $id);
        flash('success', 'Client archived.');
        redirect('/admin/clients.php');
    }

    // Merge every OTHER active client that shares THIS client's (vertical, name) INTO this one (the survivor):
    // reassign all their processes (and other client_id references) here, then archive the duplicates. The
    // survivor keeps its code/branding; the result is one client whose Process count is the sum of all of them.
    if ($action === 'merge' && $id) {
        $sv = $pdo->prepare('SELECT id, vertical_id, name FROM clients WHERE id=? AND deleted_at IS NULL');
        $sv->execute([$id]); $sv = $sv->fetch();
        if (!$sv) { flash('error', 'Client not found.'); redirect('/admin/clients.php'); }
        $grp = $pdo->prepare('SELECT id FROM clients WHERE vertical_id=? AND LOWER(name)=LOWER(?) AND deleted_at IS NULL AND id<>?');
        $grp->execute([(int) $sv['vertical_id'], $sv['name'], (int) $sv['id']]);
        $dups = array_map('intval', $grp->fetchAll(PDO::FETCH_COLUMN));
        if (!$dups) { flash('warning', 'No duplicate clients with that name to merge.'); redirect('/admin/clients.php'); }
        try {
            $res = app_merge_clients($pdo, (int) $sv['id'], $dups);   // moves processes + every client_id reference; archives dups
        } catch (Throwable $e) {
            flash('error', 'Merge failed: ' . (APP_DEBUG ? $e->getMessage() : 'server error')); redirect('/admin/clients.php');
        }
        audit_log('client.merge', 'client', (int) $sv['id'], null, ['merged' => $res['dups'], 'name' => $sv['name'], 'vertical_id' => (int) $sv['vertical_id'], 'counts' => $res]);
        if (($res['merged'] ?? 0) > 0)
            flash('success', 'Merged ' . $res['merged'] . ' duplicate(s) into "' . $sv['name'] . '" — all processes are now under one client.');
        else
            flash('warning', 'Nothing to merge — the duplicates were already consolidated.');
        redirect('/admin/clients.php');
    }

    /* ── Cross-vertical consolidation (SysAdmin only): merge same-NAME clients from OTHER verticals INTO this one.
     *    Master data is shared, so the survivor's processes/facilities/providers then serve every vertical. ── */
    if ($action === 'merge_cross' && $id) {
        if (!$crossMergeEnabled) { flash('error', 'Cross-vertical merge is disabled — this system keeps separate per-vertical copies. Use “Clone tree” to copy a tree into another vertical.'); redirect('/admin/clients.php'); }
        if (!$isSysadmin) { flash('error', 'Only a SysAdmin can merge clients across verticals.'); redirect('/admin/clients.php'); }
        $sv = $pdo->prepare('SELECT id, name FROM clients WHERE id=? AND deleted_at IS NULL'); $sv->execute([$id]); $sv = $sv->fetch();
        if (!$sv) { flash('error', 'Client not found.'); redirect('/admin/clients.php'); }
        $prev = '/admin/clients.php?action=merge_cross_preview&id=' . (int) $sv['id'];
        // Merge the EXACT records the SysAdmin ticked on the preview (not a blind re-derive by name), re-validating
        // each is still a live, same-NAME client other than the survivor. This lets a coincidental same-name match be
        // deselected, and prevents a client created/renamed after the preview (or an injected id) being swept in.
        $picked = array_values(array_filter(array_map('intval', (array) ($_POST['dup_ids'] ?? []))));
        if (!$picked) { flash('warning', 'Select at least one client to merge.'); redirect($prev); }
        $ph = implode(',', array_fill(0, count($picked), '?'));
        $chk = $pdo->prepare("SELECT id FROM clients WHERE id IN ($ph) AND deleted_at IS NULL AND LOWER(name)=LOWER(?) AND id<>?");
        $chk->execute(array_merge($picked, [$sv['name'], (int) $sv['id']]));
        $dups = array_map('intval', $chk->fetchAll(PDO::FETCH_COLUMN));
        if (!$dups) { flash('error', 'None of the selected clients are valid same-name records to merge.'); redirect($prev); }
        try {
            $res = app_merge_clients($pdo, (int) $sv['id'], $dups);
        } catch (Throwable $e) {
            flash('error', 'Cross-vertical merge failed: ' . (APP_DEBUG ? $e->getMessage() : 'server error')); redirect('/admin/clients.php');
        }
        audit_log('client.merge_cross', 'client', (int) $sv['id'], null, ['merged' => $res['dups'], 'name' => $sv['name'], 'counts' => $res]);
        if (($res['merged'] ?? 0) > 0)
            flash('success', 'Merged ' . $res['merged'] . ' client(s) from other verticals into "' . $sv['name'] . '". Its facilities & providers now serve every vertical.');
        else
            flash('warning', 'Nothing to merge — the selected duplicates were already consolidated.');
        redirect('/admin/clients.php');
    }
}

/* ---------------------------------------------------------- GET */
$pageTitle = 'Clients';
require __DIR__ . '/../includes/header.php';

$verticals = $pdo->query("SELECT id, name, code FROM verticals WHERE deleted_at IS NULL ORDER BY name")->fetchAll();

if ($action === 'new' || $action === 'edit') {
    $row = [
        'id'=>0,'vertical_id'=>0,'name'=>'','code'=>'','spoc_name'=>'','spoc_email'=>'','spoc_phone'=>'',
        'sla_notes'=>'','timezone'=>'Asia/Kolkata','status'=>'active',
    ];
    $br = ['primary_color'=>'#206bc4','login_slug'=>'','login_message'=>'',
           'show_historical_to_client'=>1,'allow_client_upload'=>0,'allow_raw_data'=>0];
    if ($action === 'edit' && $id) {
        $stmt = $pdo->prepare('SELECT * FROM clients WHERE id=? AND deleted_at IS NULL');
        $stmt->execute([$id]);
        $row = $stmt->fetch() ?: $row;
        if (!$row['id']) { flash('error','Client not found.'); redirect('/admin/clients.php'); }
        $brStmt = $pdo->prepare('SELECT * FROM client_branding WHERE client_id=?');
        $brStmt->execute([$id]);
        $br = $brStmt->fetch() ?: $br;
    }
?>
<div class="page-header"><div class="container-xl">
    <h2 class="page-title"><?= $action === 'edit' ? 'Edit client' : 'New client' ?></h2>
    <div class="text-secondary">Belongs to a Vertical. Has 1:1 branding for the client portal.</div>
</div></div>
<div class="page-body"><div class="container-xl">
<form method="POST" action="<?= e(url('/admin/clients.php?action=save')) ?>">
    <?= csrf_field() ?>
    <input type="hidden" name="id" value="<?= (int) $row['id'] ?>">
    <div class="row g-3">
        <div class="col-12">
            <div class="card"><div class="card-header"><h3 class="card-title">Basic info</h3></div>
                <div class="card-body row g-3">
                    <div class="col-md-4">
                        <label class="form-label required">Vertical</label>
                        <select name="vertical_id" class="form-select" required>
                            <option value="">-- choose --</option>
                            <?php foreach ($verticals as $v): ?>
                                <option value="<?= (int) $v['id'] ?>" <?= $row['vertical_id'] == $v['id'] ? 'selected' : '' ?>>
                                    <?= e($v['name']) ?> (<?= e($v['code']) ?>)
                                </option>
                            <?php endforeach; ?>
                        </select>
                    </div>
                    <div class="col-md-5">
                        <label class="form-label required">Client name</label>
                        <input type="text" name="name" class="form-control" required maxlength="200" value="<?= e($row['name']) ?>">
                    </div>
                    <div class="col-md-3">
                        <label class="form-label required">Code</label>
                        <input type="text" name="code" class="form-control text-uppercase" required maxlength="50" value="<?= e($row['code']) ?>" placeholder="BCH">
                    </div>
                    <div class="col-md-4">
                        <label class="form-label">SPOC name</label>
                        <input type="text" name="spoc_name" class="form-control" maxlength="150" value="<?= e($row['spoc_name']) ?>">
                    </div>
                    <div class="col-md-4">
                        <label class="form-label">SPOC email</label>
                        <input type="email" name="spoc_email" class="form-control" maxlength="191" value="<?= e($row['spoc_email']) ?>">
                    </div>
                    <div class="col-md-4">
                        <label class="form-label">SPOC phone</label>
                        <input type="text" name="spoc_phone" class="form-control" maxlength="50" value="<?= e($row['spoc_phone']) ?>">
                    </div>
                    <div class="col-md-4">
                        <label class="form-label">Timezone</label>
                        <input type="text" name="timezone" class="form-control" value="<?= e($row['timezone']) ?>" placeholder="Asia/Kolkata">
                    </div>
                    <div class="col-md-4">
                        <label class="form-label">Status</label>
                        <select name="status" class="form-select">
                            <option value="active"   <?= $row['status']==='active'   ? 'selected':'' ?>>Active</option>
                            <option value="inactive" <?= $row['status']==='inactive' ? 'selected':'' ?>>Inactive</option>
                        </select>
                    </div>
                    <div class="col-12">
                        <label class="form-label">SLA notes</label>
                        <textarea name="sla_notes" class="form-control" rows="2" maxlength="2000"><?= e($row['sla_notes']) ?></textarea>
                    </div>
                </div>
            </div>
        </div>

        <div class="col-12">
            <div class="card"><div class="card-header"><h3 class="card-title">Branded client portal</h3></div>
                <div class="card-body row g-3">
                    <div class="col-md-6">
                        <label class="form-label required">Login slug</label>
                        <div class="input-group">
                            <span class="input-group-text">/client/</span>
                            <input type="text" name="login_slug" class="form-control" required maxlength="80" value="<?= e($br['login_slug']) ?>" placeholder="blue-central">
                            <span class="input-group-text">/login</span>
                        </div>
                    </div>
                    <div class="col-md-3">
                        <label class="form-label">Primary color</label>
                        <input type="color" name="primary_color" class="form-control form-control-color" value="<?= e($br['primary_color']) ?>">
                    </div>
                    <div class="col-12">
                        <label class="form-label">Login message</label>
                        <input type="text" name="login_message" class="form-control" maxlength="200" value="<?= e($br['login_message']) ?>">
                    </div>
                    <div class="col-md-4">
                        <label class="form-check">
                            <input type="checkbox" name="show_historical_to_client" value="1" <?= !empty($br['show_historical_to_client']) ? 'checked':'' ?> class="form-check-input">
                            <span class="form-check-label">Show historical snapshots</span>
                        </label>
                    </div>
                    <div class="col-md-4">
                        <label class="form-check">
                            <input type="checkbox" name="allow_client_upload" value="1" <?= !empty($br['allow_client_upload']) ? 'checked':'' ?> class="form-check-input">
                            <span class="form-check-label">Allow client to upload data</span>
                        </label>
                    </div>
                    <div class="col-md-4">
                        <label class="form-check">
                            <input type="checkbox" name="allow_raw_data" value="1" <?= !empty($br['allow_raw_data']) ? 'checked':'' ?> class="form-check-input">
                            <span class="form-check-label">Allow client to view raw row-level data</span>
                        </label>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="form-footer d-flex gap-2 mt-3">
        <a href="<?= e(url('/admin/clients.php')) ?>" class="btn btn-link">Cancel</a>
        <button type="submit" class="btn btn-primary"><i class="ti ti-check me-1"></i>Save</button>
    </div>
</form>
</div></div>
<?php
} elseif ($action === 'merge_cross_preview' && $id && $isSysadmin && $crossMergeEnabled) {
    /* Dry-run preview of a cross-vertical consolidation: show the survivor + the same-name clients in other
       verticals and what will move, before the SysAdmin confirms. Nothing is changed here. */
    $sv = $pdo->prepare("SELECT c.id,c.name,c.code,v.name vn FROM clients c JOIN verticals v ON v.id=c.vertical_id WHERE c.id=? AND c.deleted_at IS NULL");
    $sv->execute([$id]); $sv = $sv->fetch();
    if (!$sv) { flash('error', 'Client not found.'); redirect('/admin/clients.php'); }
    $grp = $pdo->prepare("SELECT c.id,c.name,c.code,v.name vn FROM clients c JOIN verticals v ON v.id=c.vertical_id
                          WHERE LOWER(c.name)=LOWER(?) AND c.deleted_at IS NULL AND c.id<>? ORDER BY v.name");
    $grp->execute([$sv['name'], (int) $sv['id']]);
    $dups = $grp->fetchAll();
    $cnt = function (int $cid) use ($pdo) {
        $f = fn($sql) => (int) $pdo->query($sql)->fetchColumn();
        return [
            'proc'  => $f("SELECT COUNT(*) FROM processes WHERE client_id=$cid AND deleted_at IS NULL"),
            'fac'   => $f("SELECT COUNT(*) FROM coding_facilities f JOIN processes p ON p.id=f.process_id WHERE p.client_id=$cid"),
            'chart' => $f("SELECT COUNT(*) FROM coding_inventory WHERE client_id=$cid"),
            'sheet' => $f("SELECT COUNT(*) FROM coding_billing_sheets WHERE client_id=$cid"),
            'scope' => $f("SELECT COUNT(*) FROM coding_user_scope WHERE client_id=$cid"),
            'users' => $f("SELECT COUNT(*) FROM users WHERE client_id=$cid"),
        ];
    };
    $cols = ['proc'=>'Processes','fac'=>'Facilities','chart'=>'Charts','sheet'=>'Billing sheets','scope'=>'Alignments','users'=>'Portal users'];
?>
<div class="page-header"><div class="container-xl"><h2 class="page-title"><i class="ti ti-arrows-join-2 me-2 text-azure"></i>Merge across verticals — preview</h2>
    <div class="text-secondary">Consolidate every record of <strong><?= e($sv['name']) ?></strong> into one shared client. Nothing changes until you confirm.</div></div></div>
<div class="page-body"><div class="container-xl">
    <?php if (!$dups): ?>
        <div class="alert alert-info">No same-name clients exist in other verticals — nothing to merge. <a href="<?= e(url('/admin/clients.php')) ?>">Back to clients</a>.</div>
    <?php else: ?>
    <form method="POST" action="<?= e(url('/admin/clients.php?action=merge_cross&id=' . (int)$sv['id'])) ?>"
          onsubmit="return confirm('Merge the TICKED client(s) into <?= e($sv['code']) ?>? This repoints all their data and archives them.');">
        <?= csrf_field() ?>
        <div class="card">
            <div class="card-header"><h3 class="card-title">Tick the records that are the SAME practice. The ticked rows merge into the survivor; the rest are left untouched.</h3></div>
            <div class="table-responsive"><table class="table table-vcenter card-table">
                <thead><tr><th class="w-1">Merge?</th><th>Client</th><th>Code</th><th>Vertical</th><th></th><?php foreach ($cols as $l) echo '<th class="text-center">'.e($l).'</th>'; ?></tr></thead>
                <tbody>
                    <?php $svc = $cnt((int)$sv['id']); ?>
                    <tr class="table-success">
                        <td class="text-center"><i class="ti ti-lock text-secondary" title="survivor — kept"></i></td>
                        <td><strong><?= e($sv['name']) ?></strong></td><td><code><?= e($sv['code']) ?></code></td><td><?= e($sv['vn']) ?></td>
                        <td><span class="badge bg-success">KEEP (survivor)</span></td>
                        <?php foreach ($cols as $k=>$l) echo '<td class="text-center">'.(int)$svc[$k].'</td>'; ?>
                    </tr>
                    <?php foreach ($dups as $d): $dc = $cnt((int)$d['id']); ?>
                    <tr>
                        <td class="text-center"><input class="form-check-input m-0" type="checkbox" name="dup_ids[]" value="<?= (int)$d['id'] ?>" checked></td>
                        <td><?= e($d['name']) ?></td><td><code><?= e($d['code']) ?></code></td><td><?= e($d['vn']) ?></td>
                        <td><span class="badge bg-warning">archive → merge in</span></td>
                        <?php foreach ($cols as $k=>$l) echo '<td class="text-center">'.(int)$dc[$k].'</td>'; ?>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table></div>
            <div class="card-footer">
                <div class="text-secondary small mb-2"><strong>Check the codes carefully</strong> — matching is by name, so untick any row that is a different practice that happens to share this name. Ticked records' processes, facilities, charts, billing sheets, alignments and portal users move onto <strong><?= e($sv['code']) ?></strong>; work keyed by process/chart is preserved. This cannot be auto-undone (archived clients are soft-deleted).</div>
                <a href="<?= e(url('/admin/clients.php')) ?>" class="btn btn-link">Cancel</a>
                <button class="btn btn-azure"><i class="ti ti-arrows-join-2 me-1"></i>Merge ticked into <?= e($sv['code']) ?></button>
            </div>
        </div>
    </form>
    <?php endif; ?>
</div></div>
<?php
} else {
    $q = trim((string) input('q'));
    $verticalFilter = (int) input('vertical_id');
    $showArchived = (int) input('archived') === 1;
    $params = [];
    $where = $showArchived ? 'WHERE c.deleted_at IS NOT NULL' : 'WHERE c.deleted_at IS NULL';
    if ($q !== '') { $where .= ' AND (c.name LIKE ? OR c.code LIKE ?)'; $params[] = "%$q%"; $params[] = "%$q%"; }
    if ($verticalFilter) { $where .= ' AND c.vertical_id = ?'; $params[] = $verticalFilter; }
    $stmt = $pdo->prepare("
        SELECT c.*, v.name AS vertical_name,
               (SELECT COUNT(*) FROM processes p WHERE p.client_id = c.id AND p.deleted_at IS NULL) AS process_count,
               (SELECT COUNT(*) FROM clients c2 WHERE c2.vertical_id = c.vertical_id AND LOWER(c2.name) = LOWER(c.name) AND c2.deleted_at IS NULL) AS name_dups,
               (SELECT COUNT(*) FROM clients c3 WHERE LOWER(c3.name) = LOWER(c.name) AND c3.deleted_at IS NULL) AS name_dups_all
        FROM clients c
        JOIN verticals v ON v.id = c.vertical_id
        $where
        ORDER BY v.name, c.name, c.id
        LIMIT 200");
    $stmt->execute($params);
    $rows = $stmt->fetchAll();
?>
<div class="page-header"><div class="container-xl">
    <div class="row align-items-center">
        <div class="col">
            <h2 class="page-title"><?= $showArchived ? 'Archived clients' : 'Clients' ?></h2>
            <div class="text-secondary"><?= $showArchived ? 'Soft-deleted clients. Restore one to make it active again (a merged client comes back as an empty shell — its data moved to the survivor).' : 'Each client belongs to a Vertical and contains Processes.' ?></div>
        </div>
        <div class="col-auto d-flex gap-2">
            <?php if ($showArchived): ?>
                <a href="<?= e(url('/admin/clients.php')) ?>" class="btn btn-outline-secondary"><i class="ti ti-arrow-back-up me-1"></i>Back to active</a>
            <?php else: ?>
                <a href="<?= e(url('/admin/clients.php?archived=1')) ?>" class="btn btn-outline-secondary"><i class="ti ti-archive me-1"></i>Show archived</a>
                <a href="<?= e(url('/admin/clients.php?action=new')) ?>" class="btn btn-primary"><i class="ti ti-plus me-1"></i>New client</a>
            <?php endif; ?>
        </div>
    </div>
</div></div>

<div class="page-body"><div class="container-xl">
    <div class="card">
        <div class="card-header">
            <form method="GET" class="d-flex w-100 gap-2">
                <input type="text" name="q" class="form-control" placeholder="Search by name or code..." value="<?= e($q) ?>">
                <select name="vertical_id" class="form-select" style="max-width:240px">
                    <option value="">All verticals</option>
                    <?php foreach ($verticals as $v): ?>
                        <option value="<?= (int) $v['id'] ?>" <?= $verticalFilter == $v['id'] ? 'selected':'' ?>><?= e($v['name']) ?></option>
                    <?php endforeach; ?>
                </select>
                <button class="btn"><i class="ti ti-search"></i></button>
                <?php if ($q !== '' || $verticalFilter): ?><a href="<?= e(url('/admin/clients.php')) ?>" class="btn btn-ghost-secondary">Clear</a><?php endif; ?>
            </form>
        </div>
        <div class="table-responsive">
            <table class="table table-vcenter card-table">
                <thead><tr>
                    <th>Client</th><th>Code</th><th>Vertical</th><th>SPOC</th>
                    <th>Status</th><th>Processes</th><th class="w-1"></th>
                </tr></thead>
                <tbody>
                <?php if (!$rows): ?>
                    <tr><td colspan="7" class="text-center text-secondary py-4"><?= $showArchived ? 'No archived clients.' : 'No clients yet.' ?></td></tr>
                <?php else: foreach ($rows as $r): ?>
                    <tr>
                        <td><strong><?= e($r['name']) ?></strong><?php if ((int)$r['name_dups'] > 1): ?> <span class="badge bg-yellow-lt" title="<?= (int)$r['name_dups'] ?> clients share this name in <?= e($r['vertical_name']) ?> — merge them into one">duplicate ×<?= (int)$r['name_dups'] ?></span><?php endif; ?><?php if ((int)$r['name_dups_all'] > (int)$r['name_dups']): ?> <span class="badge bg-azure-lt" title="This practice has a separate record in other verticals (by design — use Clone tree to copy its facilities/providers across)">in <?= (int)$r['name_dups_all'] ?> verticals</span><?php endif; ?></td>
                        <td><code><?= e($r['code']) ?></code></td>
                        <td><?= e($r['vertical_name']) ?></td>
                        <td>
                            <?php if ($r['spoc_name']): ?>
                                <?= e($r['spoc_name']) ?>
                                <?php if ($r['spoc_email']): ?><div class="small text-secondary"><?= e($r['spoc_email']) ?></div><?php endif; ?>
                            <?php else: ?>
                                <span class="text-secondary">--</span>
                            <?php endif; ?>
                        </td>
                        <td>
                            <?php if ($r['status']==='active'): ?>
                                <span class="badge bg-success-lt">active</span>
                            <?php else: ?>
                                <span class="badge bg-secondary-lt">inactive</span>
                            <?php endif; ?>
                        </td>
                        <td><span class="badge bg-blue-lt"><?= (int) $r['process_count'] ?></span></td>
                        <td>
                            <div class="btn-list flex-nowrap">
                                <?php if ($showArchived): ?>
                                <form method="POST" action="<?= e(url('/admin/clients.php?action=restore&id=' . $r['id'])) ?>"
                                      onsubmit="return confirm('Restore client \'<?= e($r['name']) ?>\' (code <?= e($r['code']) ?>)? If it was merged, it comes back empty — its data stayed with the survivor.');">
                                    <?= csrf_field() ?>
                                    <button class="btn btn-sm btn-success text-nowrap"><i class="ti ti-arrow-back-up me-1"></i>Restore</button>
                                </form>
                                <?php else: ?>
                                <?php if ((int)$r['name_dups'] > 1): ?>
                                <form method="POST" action="<?= e(url('/admin/clients.php?action=merge&id=' . $r['id'])) ?>"
                                      onsubmit="return confirm('Merge the other client(s) named \'<?= e($r['name']) ?>\' in <?= e($r['vertical_name']) ?> INTO this one (code <?= e($r['code']) ?>)? Their processes move here; the duplicates are archived.');">
                                    <?= csrf_field() ?>
                                    <button class="btn btn-sm btn-warning text-nowrap" title="Merge same-name clients into this one"><i class="ti ti-arrows-join me-1"></i>Merge here</button>
                                </form>
                                <?php endif; ?>
                                <?php if ($crossMergeEnabled && $isSysadmin && (int)$r['name_dups_all'] > (int)$r['name_dups']): ?>
                                <a href="<?= e(url('/admin/clients.php?action=merge_cross_preview&id=' . $r['id'])) ?>" class="btn btn-sm btn-azure text-nowrap" title="Consolidate this practice's records from all verticals into this one shared client"><i class="ti ti-arrows-join-2 me-1"></i>Merge verticals</a>
                                <?php endif; ?>
                                <a href="<?= e(url('/admin/clients.php?action=edit&id=' . $r['id'])) ?>" class="btn btn-sm">
                                    <i class="ti ti-edit"></i>
                                </a>
                                <form method="POST" action="<?= e(url('/admin/clients.php?action=delete&id=' . $r['id'])) ?>"
                                      onsubmit="return confirm('Archive client \'<?= e($r['name']) ?>\'?');">
                                    <?= csrf_field() ?>
                                    <button class="btn btn-sm btn-ghost-danger"><i class="ti ti-trash"></i></button>
                                </form>
                                <?php endif; ?>
                            </div>
                        </td>
                    </tr>
                <?php endforeach; endif; ?>
                </tbody>
            </table>
        </div>
    </div>
</div></div>
<?php
}
require __DIR__ . '/../includes/footer.php';
