from __future__ import annotations
from decimal import Decimal, InvalidOperation
from pathlib import Path
from sqlite3 import Connection
from jarvis_finance.audit.log import record_audit_event
from .common import ImportResult, clean, create_import_session, require_text, source_hash, stable_id, utc_now
from .dry_run import read_csv_rows
from .row_hash import compute_row_hash
REQUIRED_COLUMNS={"account_name","balance_date","currency","amount_original"}

def dec(v,line,field):
    try: return Decimal(clean(v))
    except (InvalidOperation, ValueError) as exc: raise ValueError(f"line {line}: {field} invalid decimal") from exc

def acct(conn,name):
    r=conn.execute('SELECT account_id FROM accounts WHERE account_name=?',(name,)).fetchone(); return r['account_id'] if r else None

def import_cash_balances_csv(conn:Connection,path:str|Path,*,commit:bool,source_filename:str|None=None)->ImportResult:
    rows,errors=read_csv_rows(path,REQUIRED_COLUMNS); source_filename=source_filename or Path(path).name
    new=existing=0; vals=[]; seen=set()
    for line,row in enumerate(rows,start=2):
        try:
            rh=compute_row_hash(row)
            if rh in seen: raise ValueError(f"line {line}: duplicate row hash in source file")
            seen.add(rh); aid=acct(conn,require_text(row,'account_name',line))
            if not aid: raise ValueError(f"line {line}: account not found")
            cur=require_text(row,'currency',line).upper(); amount=dec(row.get('amount_original'),line,'amount_original'); fx=dec(row.get('fx_rate_to_chf'),line,'fx_rate_to_chf') if clean(row.get('fx_rate_to_chf')) else (Decimal('1') if cur=='CHF' else None)
            date=require_text(row,'balance_date',line); cid=stable_id('cashsnap',aid,date,cur)
            exists=conn.execute('SELECT 1 FROM transactions WHERE transaction_id=?',(cid,)).fetchone() is not None
            existing+=1 if exists else 0; new+=0 if exists else 1
            vals.append((cid,aid,date,cur,amount,fx,clean(row.get('notes')) or 'Initial cash snapshot import'))
        except ValueError as exc: errors.append(str(exc))
    status='failed' if errors else ('committed' if commit else 'dry_run_ok')
    if commit and not errors:
        now=utc_now()
        for cid,aid,date,cur,amount,fx,note in vals:
            if conn.execute('SELECT 1 FROM transactions WHERE transaction_id=?',(cid,)).fetchone(): continue
            chf=amount*fx if fx is not None else None
            conn.execute("""INSERT INTO transactions(transaction_id,transaction_type,account_id,trade_date,gross_amount_original,net_amount_original,currency_original,fx_rate_to_chf,fx_status,gross_amount_chf,net_amount_chf,source_type,is_confirmed,quality_status,notes,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,1,?,?,?)""",(cid,'initial_cash_snapshot',aid,date,str(amount),str(amount),cur,str(fx) if fx is not None else None,'ok' if fx is not None else 'missing',str(chf) if chf is not None else None,str(chf) if chf is not None else None,'csv','ok' if fx is not None else 'incomplete',note,now))
            record_audit_event(conn,source='csv_import',action='initial_cash_snapshot',entity_type='transaction',entity_id=cid,new_values={'amount_original':str(amount),'currency':cur},user_text_note=note,confirmed=True,created_by='importer')
    sid=create_import_session(conn,import_type='cash_balances',source_filename=source_filename,file_hash=source_hash(path),status=status,rows_total=len(rows),rows_imported=new if commit and not errors else 0,rows_failed=len(errors),errors=errors,notes='dry run' if not commit else None)
    return ImportResult(sid,'cash_balances',status,len(rows),new if not errors else 0,existing,len(errors),errors)
