from fastapi import APIRouter, HTTPException, Query
from typing import Optional, List, Dict, Any
from decimal import Decimal
from datetime import date
from app.core.database import get_connection

router = APIRouter(prefix="/ledger", tags=["元帳"])

def to_decimal(x) -> Decimal:
    if isinstance(x, Decimal):
        return x
    return Decimal(str(x or 0))

@router.get("/{account_id}", summary="科目別元帳（残高推移）")
def get_ledger(
    account_id: int,
    date_from: Optional[str] = Query(None, description="YYYY-MM-DD"),
    date_to: Optional[str] = Query(None, description="YYYY-MM-DD"),
):
    # 1) 科目存在チェック
    with get_connection() as conn, conn.cursor() as cur:
        cur.execute("""
            SELECT account_id, account_code, account_name, account_type
              FROM accounts
             WHERE account_id = %s
        """, (account_id,))
        account = cur.fetchone()
        if not account:
            raise HTTPException(status_code=404, detail="指定した科目が見つかりません。")

        # 2) 期間デフォルト（最小〜最大）
        if not date_from:
            cur.execute("""
                SELECT MIN(j.journal_date) AS min_d
                  FROM journal_entries j
                  JOIN journal_lines l ON l.journal_id = j.journal_id
                 WHERE l.account_id = %s
            """, (account_id,))
            row = cur.fetchone()
            date_from = (row["min_d"] or date.today()).isoformat()

        if not date_to:
            cur.execute("""
                SELECT MAX(j.journal_date) AS max_d
                  FROM journal_entries j
                  JOIN journal_lines l ON l.journal_id = j.journal_id
                 WHERE l.account_id = %s
            """, (account_id,))
            row = cur.fetchone()
            date_to = (row["max_d"] or date.today()).isoformat()

        # 3) 期首残高（date_from より前）
        cur.execute("""
            SELECT COALESCE(SUM(l.debit - l.credit), 0) AS opening
              FROM journal_lines l
              JOIN journal_entries j ON j.journal_id = l.journal_id
             WHERE l.account_id = %s
               AND j.journal_date < %s
        """, (account_id, date_from))
        opening = to_decimal(cur.fetchone()["opening"])

        # 4) 期間内明細
        cur.execute("""
            SELECT j.journal_date, j.journal_id, j.description,
                   l.debit, l.credit
              FROM journal_lines l
              JOIN journal_entries j ON j.journal_id = l.journal_id
             WHERE l.account_id = %s
               AND j.journal_date BETWEEN %s AND %s
             ORDER BY j.journal_date, j.journal_id, l.line_id
        """, (account_id, date_from, date_to))
        rows = cur.fetchall()

    # 5) 残高推移の計算（借方−貸方）
    balance = opening
    out_rows: List[Dict[str, Any]] = []
    total_debit = Decimal("0")
    total_credit = Decimal("0")

    for r in rows:
        d = to_decimal(r["debit"])
        c = to_decimal(r["credit"])
        total_debit += d
        total_credit += c
        balance += (d - c)
        out_rows.append({
            "date": r["journal_date"].isoformat(),
            "journal_id": r["journal_id"],
            "description": r["description"],
            "debit": str(d),
            "credit": str(c),
            "balance": str(balance)  # 借方残を正とする（借方−貸方）
        })

    result = {
        "account": {
            "id": account["account_id"],
            "code": account["account_code"],
            "name": account["account_name"],
            "type": account["account_type"],
        },
        "period": {"from": date_from, "to": date_to},
        "opening_balance": str(opening),
        "total_debit": str(total_debit),
        "total_credit": str(total_credit),
        "closing_balance": str(balance),
        "rows": out_rows
    }
    return result
