from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, field_validator
from enum import Enum
from psycopg.errors import UniqueViolation, CheckViolation, StringDataRightTruncation
from app.core.database import get_connection

router = APIRouter(prefix="/accounts", tags=["科目マスタ"])

class AccountType(str, Enum):
    asset = "asset"
    liability = "liability"
    equity = "equity"
    revenue = "revenue"
    expense = "expense"

class AccountCreate(BaseModel):
    account_code: str
    account_name: str
    account_type: AccountType

    @field_validator("account_code")
    @classmethod
    def validate_code(cls, v: str):
        if not v.isdigit():
            raise ValueError("科目コードは数字のみで入力してください")
        if len(v) > 20:
            raise ValueError("科目コードが長すぎます（20文字以内）")
        return v

    @field_validator("account_name")
    @classmethod
    def validate_name(cls, v: str):
        if not v.strip():
            raise ValueError("科目名を入力してください")
        if len(v) > 100:
            raise ValueError("科目名が長すぎます（100文字以内）")
        return v

@router.get("/", summary="科目一覧取得")
def list_accounts():
    with get_connection() as conn, conn.cursor() as cur:
        cur.execute("""
            SELECT account_id, account_code, account_name, account_type, is_active
            FROM accounts ORDER BY account_code
        """)
        return cur.fetchall()

@router.post("/", summary="科目登録", status_code=201)
def create_account(data: AccountCreate):
    try:
        with get_connection() as conn, conn.cursor() as cur:
            cur.execute("""
                INSERT INTO accounts (account_code, account_name, account_type)
                VALUES (%s, %s, %s) RETURNING account_id
            """, (data.account_code, data.account_name, data.account_type.value))
            new_id = cur.fetchone()["account_id"]
            conn.commit()
            return {"account_id": new_id}

    except UniqueViolation:
        # 409 也行；这里按你的要求统一 400
        raise HTTPException(status_code=400, detail="この科目コードは既に登録されています。")
    except StringDataRightTruncation:
        raise HTTPException(status_code=400, detail="入力文字数が制限を超えています。")
    except CheckViolation:
        raise HTTPException(status_code=400, detail="入力値が不正です。")
