/**
 * Tier-2 (#GUI-uplift) — date-type fidelity.
 *
 * TypeScript source very commonly types date fields as `string` (ISO strings)
 * while the database column is `DATE`/`TIMESTAMP`. The TSI adapter therefore
 * extracts `check_in: string`, the spec emits `check_in: String`, and the
 * generated form renders a plain text box instead of a date picker.
 *
 * This pass recovers the lost type from the authoritative source — the SQL
 * DDL — plus two near-universal name conventions, and upgrades String-typed
 * attributes to `DateTime` so the runtime renders a date picker (and realize
 * emits a `DateTime` column).
 *
 * Signals (any one upgrades a String attribute):
 *   1. A `*.sql` `CREATE TABLE` column of the same name typed
 *      `DATE`/`DATETIME`/`TIMESTAMP`/`TIMESTAMPTZ` (authoritative).
 *   2. The `*_at` / `*At` timestamp convention (matches realize's existing
 *      `isTimestampFieldName` promotion — consistent by construction).
 *   3. A field literally named `*_date` / `*Date`.
 *
 * Conservative: only upgrades attributes whose CURRENT type is string-ish
 * (string/String/text/varchar/char) — never overrides a real Number/Boolean/
 * relationship type. We map to `DateTime` (not a date-only `Date`) because
 * `DateTime` is fully plumbed through realize today; date-only is a later
 * polish (needs `Date` → Prisma `@db.Date` mapping).
 */
import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
import { join } from 'path';
const IGNORE_DIRS = new Set([
    'node_modules', 'dist', 'build', 'out', '.git', '.next', '.turbo',
    '.cache', 'coverage', '__pycache__', '.pytest_cache', 'target', '.idea', '.vscode',
]);
const STRINGISH = /^(?:string|text|varchar|char|nvarchar|clob)$/i;
const SQL_DATE_TYPE = /\b(?:DATE|DATETIME|TIMESTAMP(?:TZ)?|TIMESTAMP\s+WITH\s+TIME\s+ZONE)\b/i;
const TS_AT_NAME = /(?:_at|At)$/;
const TS_DATE_NAME = /(?:_date|Date)$/;
const norm = (s) => String(s ?? '').toLowerCase().replace(/_/g, '');
/** Scan *.sql files for column names typed as a SQL date/timestamp. */
function sqlDateColumnNames(sourceDir) {
    const cols = new Set();
    const walk = (dir, depth) => {
        if (depth > 8)
            return;
        let entries;
        try {
            entries = readdirSync(dir);
        }
        catch {
            return;
        }
        for (const name of entries) {
            if (IGNORE_DIRS.has(name))
                continue;
            const full = join(dir, name);
            let st;
            try {
                st = statSync(full);
            }
            catch {
                continue;
            }
            if (st.isDirectory()) {
                walk(full, depth + 1);
                continue;
            }
            if (!/\.sql$/i.test(name))
                continue;
            let src;
            try {
                src = readFileSync(full, 'utf-8');
            }
            catch {
                continue;
            }
            for (const rawLine of src.split('\n')) {
                // `  check_in DATE NOT NULL,` → column `check_in`, type DATE
                const m = rawLine.match(/^\s*["'`]?([A-Za-z_][A-Za-z0-9_]*)["'`]?\s+([A-Za-z][A-Za-z0-9_ ]*)/);
                if (!m)
                    continue;
                const col = m[1];
                if (/^(?:CREATE|PRIMARY|FOREIGN|CONSTRAINT|UNIQUE|INDEX|KEY|CHECK)$/i.test(col))
                    continue;
                if (SQL_DATE_TYPE.test(m[2]))
                    cols.add(norm(col));
            }
        }
    };
    walk(sourceDir, 0);
    return cols;
}
/**
 * Upgrade String-typed date attributes to `DateTime`. Mutates
 * `facts.entities[].attributes[].declaredType`. Returns the upgrades.
 */
export function refineDateTypes(facts, sourceDir) {
    const out = [];
    if (!facts?.entities?.length)
        return out;
    const sqlCols = sourceDir && existsSync(sourceDir) ? sqlDateColumnNames(sourceDir) : new Set();
    for (const ent of facts.entities) {
        const attrs = Array.isArray(ent?.attributes) ? ent.attributes : [];
        for (const a of attrs) {
            const name = a?.name;
            const type = a?.declaredType;
            if (!name || typeof type !== 'string' || !STRINGISH.test(type))
                continue;
            let reason = null;
            if (sqlCols.has(norm(name)))
                reason = 'sql-ddl';
            else if (TS_AT_NAME.test(name))
                reason = 'name-at';
            else if (TS_DATE_NAME.test(name))
                reason = 'name-date';
            if (!reason)
                continue;
            out.push({ modelName: String(ent?.name ?? '<anon>'), attribute: name, from: type, reason });
            a.declaredType = 'DateTime';
            console.warn(`   ℹ️  Prepass: ${ent?.name}.${name} String → DateTime (${reason})`);
        }
    }
    return out;
}
//# sourceMappingURL=date-type-refinement.js.map