"""Persistent entry freeze. It never submits orders or claims liquidation."""
from datetime import datetime, timezone, timedelta
from decimal import Decimal
from pathlib import Path
import os
import sqlite3
from infinbot_common import private_dir, timestamp, number, Rejected, private_read


class RiskState:
    def __init__(self,path,*,initialize=False,timeout_hours=6,now=None):
        self.path=Path(path).absolute();self.now=now or (lambda:datetime.now(timezone.utc))
        if initialize:
            private_dir(self.path.parent)
            fd=os.open(self.path,os.O_CREAT|os.O_EXCL|os.O_WRONLY,0o600);os.close(fd)
            with sqlite3.connect(self.path) as c:
                c.executescript('CREATE TABLE control(id INTEGER PRIMARY KEY CHECK(id=1),frozen INTEGER CHECK(frozen=1),deadline TEXT NOT NULL,reason TEXT NOT NULL);CREATE TABLE events(id INTEGER PRIMARY KEY,event TEXT NOT NULL,observed_at TEXT NOT NULL);CREATE TABLE worker_heartbeats(worker TEXT PRIMARY KEY,observed_at TEXT NOT NULL,status TEXT NOT NULL);')
                hours=number(timeout_hours,True)
                if hours>6:raise Rejected('Maximum worker lifetime is six hours')
                c.execute('INSERT INTO control VALUES(1,1,?,?)',((self.now()+timedelta(seconds=float(hours)*3600)).isoformat(),'INITIAL_INGRESS_FREEZE'))
        private_read(self.path,16*1024*1024)

    def connect(self):
        return sqlite3.connect(self.path.as_uri()+'?mode=rw',uri=True,timeout=3)

    def status(self):
        with self.connect() as c:
            row=c.execute('SELECT frozen,deadline,reason FROM control WHERE id=1').fetchone()
        if not row or row[0]!=1:raise Rejected('Risk state invalid; entries blocked')
        expired=self.now()>=datetime.fromisoformat(row[1])
        return {'entries_frozen':True,'deadline':row[1],'deadline_expired':expired,'reason':row[2],
                'allocated_units':'0.0000','live_execution_enabled':False,'liquidation_verified':False}

    def freeze(self,reason):
        if not isinstance(reason,str) or not reason.strip() or len(reason)>200:raise Rejected('Bounded incident reference required')
        with self.connect() as c:
            c.execute('BEGIN IMMEDIATE');c.execute('UPDATE control SET frozen=1,reason=? WHERE id=1',(reason,))
            c.execute('INSERT INTO events(event,observed_at) VALUES(?,?)',(reason,self.now().isoformat()))
        return self.status()

    def observe(self,baseline_equity,current_equity,*,feed_fresh,reconciled):
        baseline=number(baseline_equity,True);equity=number(current_equity)
        drawdown=max(Decimal(0),(baseline-equity)/baseline*100)
        if not feed_fresh or not reconciled:self.freeze('FEED_OR_RECONCILIATION_UNVERIFIED')
        if drawdown>=Decimal(3):self.freeze('DRAWDOWN_BREAKER_TRIPPED')
        result=self.status();result['drawdown_pct']=str(drawdown);return result

    def heartbeat(self,worker):
        if worker not in ('bot-worker-crypto','bot-worker-futures'):raise Rejected('Unknown worker')
        state=self.status()
        with self.connect() as c:c.execute('INSERT INTO worker_heartbeats VALUES(?,?,?) ON CONFLICT(worker) DO UPDATE SET observed_at=excluded.observed_at,status=excluded.status',(worker,self.now().isoformat(),'ENTRY_FREEZE_ACTIVE'))
        return state
