import psycopg2
from psycopg2.extras import RealDictCursor
import json
from datetime import datetime

conn = psycopg2.connect('host=192.168.0.61 port=55432 dbname=njts_acct user=njts_app password=njts_app2025')
cur = conn.cursor(cursor_factory=RealDictCursor)

print("=" * 100)
print("【對沖測試流程】: 登録 → 修正 → 恢復原始 → 删除逆仕訳")
print("=" * 100)

# ================== 步骤 1: 創建測試數據 ==================
print("\n【步驟 1】登錄測試數據（金額10元，2025年6月）")
print("-" * 100)

cur.execute("""
INSERT INTO journal_entries (entry_date, description, fiscal_year, version, is_deleted, created_by)
VALUES (%s, %s, %s, 1, false, %s)
RETURNING journal_entry_id
""", (
    '2025-06-15',
    '【對沖測試】テスト用取引 テスト用取引',
    2025,
    'system'
))

test_entry_id = cur.fetchone()['journal_entry_id']
print(f"✓ 創建 Entry#{test_entry_id}")

# 添加明細行（売上高 account_id=41，金額10元）
cur.execute("""
INSERT INTO journal_lines (journal_entry_id, account_id, debit, credit)
VALUES (%s, %s, 0, %s)
""", (test_entry_id, 41, 10))

print(f"✓ 添加明細: 売上高 10元 貳")
conn.commit()

# 驗證
cur.execute("""
SELECT je.journal_entry_id, je.description, jl.account_id, a.account_code, jl.credit
FROM journal_entries je
LEFT JOIN journal_lines jl ON je.journal_entry_id = jl.journal_entry_id
LEFT JOIN accounts a ON jl.account_id = a.account_id
WHERE je.journal_entry_id = %s
""", (test_entry_id,))

row = cur.fetchone()
print(f"\n  Entry#{row['journal_entry_id']}: {row['account_code']} {row['account_code']} | 貳: {row['credit']}")

# ================== 步驟 2: 計算修正前的試算表 ==================
print("\n【步驟 2】修正前的試算表（2025年6月 account 701）")
print("-" * 100)

cur.execute("""
SELECT 
  SUM(CASE WHEN jl.debit::numeric > 0 THEN jl.debit::numeric ELSE 0 END) as debit_total,
  SUM(CASE WHEN jl.credit::numeric > 0 THEN jl.credit::numeric ELSE 0 END) as credit_total
FROM journal_lines jl
JOIN journal_entries je ON jl.journal_entry_id = je.journal_entry_id
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
WHERE jl.account_id = 41
  AND EXTRACT(YEAR FROM je.entry_date) = 2025
  AND EXTRACT(MONTH FROM je.entry_date) = 6
  AND je.is_deleted = false
  AND child.journal_entry_id IS NULL
""")

result = cur.fetchone()
before_debit = result['debit_total'] if result['debit_total'] else 0
before_credit = result['credit_total'] if result['credit_total'] else 0
print(f"試算表: 借: {before_debit:,.0f} | 貳: {before_credit:,.0f}")
print(f"  (包含我們的測試Entry 10元)")

# ================== 步驟 3: 通過後端 /reverse API 創建對沖 ==================
print("\n【步驟 3】通過「修正」按鈕創建對沖（模擬 /reverse API）")
print("-" * 100)

# 手工執行 reverse 邏輯（實際應該調用後端API）
cur.execute("""
INSERT INTO journal_entries (
    entry_date,
    description,
    fiscal_year,
    version,
    is_deleted,
    created_by,
    parent_entry_id
)
VALUES (%s, %s, %s, 1, false, %s, %s)
RETURNING journal_entry_id
""", (
    '2025-06-15',
    f'[逆仕訳] 【對沖測試】テスト用取引 テスト用取引',
    2025,
    'system',
    test_entry_id
))

reverse_entry_id = cur.fetchone()['journal_entry_id']
print(f"✓ 創建逆仕訳 Entry#{reverse_entry_id}，parent_entry_id={test_entry_id}")

# 添加逆仕訳明細（借方 10元）
cur.execute("""
INSERT INTO journal_lines (journal_entry_id, account_id, debit, credit)
VALUES (%s, %s, %s, 0)
""", (reverse_entry_id, 41, 10))

print(f"✓ 添加逆仕訳明細: 売上高 10元 借")
conn.commit()

print(f"\n  parent-child 關係: Entry#{test_entry_id} ←parent- Entry#{reverse_entry_id}")

# ================== 步驟 4: 計算修正後的試算表 ==================
print("\n【步驟 4】修正後的試算表（両條應該都被過濾）")
print("-" * 100)

cur.execute("""
SELECT 
  SUM(CASE WHEN jl.debit::numeric > 0 THEN jl.debit::numeric ELSE 0 END) as debit_total,
  SUM(CASE WHEN jl.credit::numeric > 0 THEN jl.credit::numeric ELSE 0 END) as credit_total
FROM journal_lines jl
JOIN journal_entries je ON jl.journal_entry_id = je.journal_entry_id
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
WHERE jl.account_id = 41
  AND EXTRACT(YEAR FROM je.entry_date) = 2025
  AND EXTRACT(MONTH FROM je.entry_date) = 6
  AND je.is_deleted = false
  AND child.journal_entry_id IS NULL
""")

result = cur.fetchone()
after_debit = result['debit_total'] if result['debit_total'] else 0
after_credit = result['credit_total'] if result['credit_total'] else 0
print(f"試算表: 借: {after_debit:,.0f} | 貳: {after_credit:,.0f}")

# 驗證両條都被過濾
if after_debit == before_debit and after_credit == before_credit - 10:
    print(f"✓ 對沖成功！10元的借貸被抵消")
else:
    print(f"✗ 對沖失敗！期望減少10元，實際減少 {before_credit - after_credit}")

# ================== 步驟 5: 恢復原始交易 ==================
print("\n【步驟 5】恢復原始交易 + 刪除逆仕訳")
print("-" * 100)

# 恢復原始交易（清除 parent 關係）
cur.execute("""
UPDATE journal_entries
SET parent_entry_id = NULL
WHERE journal_entry_id = %s
""", (test_entry_id,))
print(f"✓ 恢復 Entry#{test_entry_id}（清除 parent_entry_id）")

# 刪除逆仕訳
cur.execute("""
UPDATE journal_entries
SET is_deleted = true
WHERE journal_entry_id = %s
""", (reverse_entry_id,))
print(f"✓ 刪除逆仕訳 Entry#{reverse_entry_id}（is_deleted = true）")
conn.commit()

# ================== 步驟 6: 計算恢復後的試算表 ==================
print("\n【步驟 6】恢復後的試算表（原始交易應該重新出現）")
print("-" * 100)

cur.execute("""
SELECT 
  SUM(CASE WHEN jl.debit::numeric > 0 THEN jl.debit::numeric ELSE 0 END) as debit_total,
  SUM(CASE WHEN jl.credit::numeric > 0 THEN jl.credit::numeric ELSE 0 END) as credit_total
FROM journal_lines jl
JOIN journal_entries je ON jl.journal_entry_id = je.journal_entry_id
LEFT JOIN journal_entries child ON child.parent_entry_id = je.journal_entry_id
WHERE jl.account_id = 41
  AND EXTRACT(YEAR FROM je.entry_date) = 2025
  AND EXTRACT(MONTH FROM je.entry_date) = 6
  AND je.is_deleted = false
  AND child.journal_entry_id IS NULL
""")

result = cur.fetchone()
final_debit = result['debit_total'] if result['debit_total'] else 0
final_credit = result['credit_total'] if result['credit_total'] else 0
print(f"試算表: 借: {final_debit:,.0f} | 貳: {final_credit:,.0f}")

if final_credit == before_credit:
    print(f"✓ 恢復成功！試算表回到初始狀態")
else:
    print(f"✗ 恢復失敗！期望 {before_credit}, 實際 {final_credit}")

# ================== 步驟 7: 最後清理 ==================
print("\n【步驟 7】清理測試數據（刪除測試 Entry）")
print("-" * 100)

cur.execute("""
UPDATE journal_entries
SET is_deleted = true
WHERE journal_entry_id = %s
""", (test_entry_id,))
conn.commit()
print(f"✓ 刪除測試 Entry#{test_entry_id}")

# ================== 測試摘要 ==================
print("\n" + "=" * 100)
print("【測試摘要】")
print("=" * 100)
print(f"✓ 步驟 1: 創建 Entry#{test_entry_id}（金額10元）")
print(f"✓ 步驟 2: 修正前試算表: 借 {before_debit:,.0f} | 貳 {before_credit:,.0f}")
print(f"✓ 步驟 3: 創建逆仕訳 Entry#{reverse_entry_id}，建立 parent-child 關係")
print(f"✓ 步驟 4: 修正後試算表: 借 {after_debit:,.0f} | 貳 {after_credit:,.0f}（10元被對沖✓）")
print(f"✓ 步驟 5: 恢復原始交易 + 刪除逆仕訳")
print(f"✓ 步驟 6: 恢復後試算表: 借 {final_debit:,.0f} | 貳 {final_credit:,.0f}（回到初始狀態✓）")
print(f"✓ 步驟 7: 清理測試數據")
print("\n所有步驟完成！✓")
print("=" * 100)

conn.close()
