"""Peewee migrations -- 185_MAIN.py.

Drop ``NOT NULL`` from ``taxdocument.customer_record_id`` by patching
``sqlite_master`` in place.

SQLite has no ``ALTER COLUMN DROP NOT NULL``. The standard
``migrator.drop_not_null`` helper works by rebuilding the table
(``DROP``/``CREATE``/``INSERT``/``RENAME``), which fails with
"attempt to write a readonly database" on plants running the
PyInstaller-built dispatch.exe on Windows. Patching the
``CREATE TABLE`` text via ``PRAGMA writable_schema`` is a single
small ``UPDATE`` and avoids the rebuild path entirely.
"""

import peewee as pw
from peewee_migrate import Migrator


_NEEDLE = '"customer_record_id" INTEGER NOT NULL'
_REPLACEMENT = '"customer_record_id" INTEGER'


def _patch_schema(database: pw.Database, needle: str, replacement: str) -> None:
    row = database.execute_sql(
        "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'taxdocument'"
    ).fetchone()
    old_sql = row[0]
    if needle not in old_sql:
        return  # already in the target state
    new_sql = old_sql.replace(needle, replacement)
    database.execute_sql("PRAGMA writable_schema = ON")
    try:
        database.execute_sql(
            "UPDATE sqlite_master SET sql = ? WHERE type = 'table' AND name = 'taxdocument'",
            (new_sql,),
        )
    finally:
        # Use OFF (not RESET): RESET forces an in-connection schema reload, which
        # on Windows + WAL + the migrator's secondary connection causes the next
        # write on this connection (peewee-migrate's INSERT into migratehistory)
        # to fail with "attempt to write a readonly database". OFF just clears
        # the writable_schema flag; the on-disk change has already been written
        # and is picked up by the next freshly opened connection.
        database.execute_sql("PRAGMA writable_schema = OFF")


def migrate(migrator: Migrator, database: pw.Database, *, fake: bool = False) -> None:
    migrator.run(_patch_schema, database, _NEEDLE, _REPLACEMENT)


def rollback(migrator: Migrator, database: pw.Database, *, fake: bool = False) -> None:
    migrator.run(_patch_schema, database, _REPLACEMENT + ",", _NEEDLE + ",")
