"""
Module: engine_bridge.py
Description: Cầu nối (Wrapper) giữa dự án Accountant và thư viện Finac.
Giúp ánh xạ các nghiệp vụ kế toán Việt Nam vào Engine Finac.
"""

try:
    import finac
    HAS_FINAC = True
except ImportError:
    HAS_FINAC = False

import os
import sqlite3
from typing import List, Dict, Optional

class FinacEngine:
    def __init__(self, db_path: str):
        self.db_path = db_path
        if not HAS_FINAC:
            print("⚠️ FINAC engine not found. Accounting engine features disabled.")
            return

        # Khởi tạo Finac với SQLite
        # Finac dùng SQLAlchemy internally
        db_uri = f"sqlite:///{os.path.abspath(db_path)}"
        finac.init(db=db_uri, multiplier=1000) # multiplier=1000 để lưu 3 chữ số thập phân dưới dạng số nguyên


    def setup_coa(self, accounts: List[Dict]):
        """
        Thiết lập Danh mục tài khoản (COA) vào Finac.
        Finac entities: Asset (loại tiền), Account (tài khoản).
        """
        # 1. Khai báo Asset mặc định (VND)
        try:
            finac.create_asset("VND", precision=0)
        except:
            pass # Đã tồn tại

        # 2. Tạo các tài khoản
        for acc in accounts:
            code = acc["code"]
            acc_type = acc["type"] # asset, liability, equity, revenue, expense
            
            # Khởi tạo tài khoản trong finac
            # Trong finac, type có thể là: 'asset', 'liability', 'revenue', 'expense'
            # 'equity' thường được coi là 'liability' trong double-entry cơ bản hoặc tài khoản đặc biệt.
            f_type = acc_type if acc_type in ['asset', 'liability', 'revenue', 'expense'] else 'liability'
            
            try:
                finac.create_account(
                    account=code,
                    asset="VND",
                    tp=f_type,
                    note=acc["name"]
                )
            except Exception as e:
                # Bỏ qua nếu đã tồn tại
                pass

    def add_transaction(self, 
                        dt: str, 
                        entries: List[Dict], 
                        description: str, 
                        tag: str = ""):
        """
        Thêm một bút toán kép vào Finac.
        entries: list of {account, debit, credit}
        """
        # Finac hỗ trợ transaction phức tạp (nhiều nợ nhiều có qua finac.transaction)
        # Hoặc đơn giản hơn qua finac.tr()
        
        # Chuyển đổi entries sang định dạng finac
        # Trong double-entry truyền thống: Nợ (Debit) là số dương, Có (Credit) là số âm
        for entry in entries:
            acc = entry["account"]
            amount = entry.get("debit", 0) - entry.get("credit", 0)
            
            if amount == 0:
                continue
                
            finac.tr(
                account=acc,
                amount=amount,
                date=dt,
                tag=tag,
                note=description
            )

    def get_balance(self, account_code: str) -> float:
        """Lấy số dư tài khoản, trả về 0 nếu Finac không khả dụng."""
        if not HAS_FINAC:
            return 0.0
        try:
            return float(finac.account_balance(account_code))
        except Exception:
            # Một số phiên bản finac khác tên hàm API.
            try:
                return float(finac.balance(account_code))
            except Exception:
                return 0.0

    def get_statement(self, account_code: str, start=None, end=None):
        """Lấy sao kê tài khoản."""
        if not HAS_FINAC:
            return []
        return finac.account_statement(account_code, start=start, end=end)


# Singleton-ish instance manager
_engines = {}

def get_engine(db_path: str) -> FinacEngine:
    if db_path not in _engines:
        _engines[db_path] = FinacEngine(db_path)
    return _engines[db_path]
