"""Generate private first-database provisioning SQL/config. Never connects to DM."""
import json,secrets,re,os
from pathlib import Path
root=Path(__file__).resolve().parent
if not (root/'manifest.json').is_file():raise SystemExit('Run the copy inside the extracted migration package')
private=root/'private'
if private.exists():raise SystemExit('private already exists: inspect prior preparation; refusing to overwrite passwords')
def ask(label,default):return input(label+' ['+default+']: ').strip()or default
host=ask('DM host','127.0.0.1');port=ask('DM port','5236');instance=ask('INSTANCE_NAME','DMSERVER')
build=ask('Exact SELECT ID_CODE result','--03134284488-20260902-347071-20200 Pack30')
tbs=ask('First database tablespace','FOODSAFE_TBS');app=ask('First database user','FOODSAFE_APP');probe=ask('Dedicated temporary probe user','FOODSAFE1_PROBE')
dbf=ask('New tablespace datafile','/data/dmdata/foodsafe/FOODSAFE_TBS.DBF');disql=ask('DIsql executable','/home/dmdba/dmdbms/bin/disql')
if not re.fullmatch(r'[A-Za-z0-9.:-]+',host)or not port.isdigit()or not 1<=int(port)<=65535:raise SystemExit('Invalid host/port')
if not all(re.fullmatch(r'[A-Z][A-Z0-9_]{0,62}',x)for x in (instance,tbs,app,probe)):raise SystemExit('Use uppercase safe identifiers')
if app in ('SYS','SYSDBA','SYSAUDITOR','SYSSSO')or app==probe or not re.fullmatch(r'FOODSAFE[A-Z0-9_]*_PROBE',probe):raise SystemExit('Unsafe business/probe account')
if not dbf.startswith('/data/')or not re.fullmatch(r'/[A-Za-z0-9_./-]+',dbf)or '..'in Path(dbf).parts:raise SystemExit('Use approved new /data datafile path without special characters')
if not Path(disql).is_file()or not os.access(disql,os.X_OK):raise SystemExit('DIsql executable missing')
if Path(dbf).exists():raise SystemExit('Datafile already exists: refusing to overwrite')
private.mkdir(mode=0o700)
passwords={app:'Fs_'+secrets.token_hex(18)+'Z9',probe:'Pr_'+secrets.token_hex(18)+'Z9'}
def lit(x):return "'"+str(x).replace("'","''")+"'"
sql=['WHENEVER SQLERROR EXIT FAILURE ROLLBACK','DECLARE N INT; V_INSTANCE VARCHAR(128); V_PORT VARCHAR(32); V_MODE VARCHAR(32); V_BUILD VARCHAR(256); V_USER VARCHAR(128); V_CASE INT; V_UNICODE INT; V_PAGE INT;','BEGIN',
 " SELECT PARA_VALUE INTO V_INSTANCE FROM SYS.V$DM_INI WHERE PARA_NAME='INSTANCE_NAME';",
 " SELECT PARA_VALUE INTO V_PORT FROM SYS.V$DM_INI WHERE PARA_NAME='PORT_NUM';",
 " SELECT PARA_VALUE INTO V_MODE FROM SYS.V$DM_INI WHERE PARA_NAME='COMPATIBLE_MODE';",
 ' SELECT ID_CODE,USER,SF_GET_CASE_SENSITIVE_FLAG(),SF_GET_UNICODE_FLAG(),PAGE() INTO V_BUILD,V_USER,V_CASE,V_UNICODE,V_PAGE FROM DUAL;',
 ' IF TRIM(V_INSTANCE)<>'+lit(instance)+' OR TRIM(V_PORT)<>'+lit(port)+' OR TRIM(V_MODE)<>\'4\' OR V_BUILD<>'+lit(build)+" OR V_USER<>'SYSDBA' OR V_CASE<>0 OR V_UNICODE<>1 OR V_PAGE<>32768 THEN RAISE_APPLICATION_ERROR(-20004,'Target fingerprint mismatch; stop'); END IF;",
 " SELECT COUNT(*) INTO N FROM DBA_USERS WHERE USERNAME IN ('"+app+"','"+probe+"');", " IF N<>0 THEN RAISE_APPLICATION_ERROR(-20002,'Target user exists; stop'); END IF;", " SELECT COUNT(*) INTO N FROM DBA_TABLESPACES WHERE TABLESPACE_NAME='"+tbs+"';", " IF N<>0 THEN RAISE_APPLICATION_ERROR(-20003,'Target tablespace exists; stop'); END IF;",'END;','/',"CREATE TABLESPACE \""+tbs+"\" DATAFILE '"+dbf+"' SIZE 2048 AUTOEXTEND ON NEXT 256 MAXSIZE 32768;"]
for user,pw in passwords.items():
 sql+=['CREATE USER "'+user+'" IDENTIFIED BY "'+pw+'" DEFAULT TABLESPACE "'+tbs+'" DEFAULT INDEX TABLESPACE "'+tbs+'";','GRANT CREATE SESSION TO "'+user+'";','GRANT RESOURCE TO "'+user+'";','GRANT SELECT ON SYS.V$DM_INI TO "'+user+'";']
 cfg={'host':host,'port':int(port),'user':user,'password':pw,'expectedInstance':instance,'expectedCompatibleMode':4,'expectedTablespace':tbs,'expectedBuild':build,'expectedTargetUser':app,'disql':disql,'driverPaths':[str(root)],'dataset':'foodsafe-first-20261021'}
 p=private/('probe.private.json'if user==probe else'import.private.json')
 with p.open('x')as f:json.dump(cfg,f,indent=2)
 p.chmod(0o600)
sql+=['SELECT USERNAME,DEFAULT_TABLESPACE FROM DBA_USERS WHERE USERNAME IN (\''+app+'\',\''+probe+'\');','SELECT TABLESPACE_NAME FROM DBA_TABLESPACES WHERE TABLESPACE_NAME=\''+tbs+'\';']
p=private/'01-provision.sql'
with p.open('x')as f:f.write('\n'.join(sql)+'\n')
p.chmod(0o600)
print('Private SQL and two connection files generated under '+str(private))
print('Nothing has been executed against the database. Follow INSTALL.md; do not share passwords or private files.')
