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


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


# ======================================================
# Enum：科目種別
# ======================================================
class AccountType(str, Enum):
    asset = "asset"
    liability = "liability"
    equity = "equity"
    revenue = "revenue"
    expense = "expense"


# ======================================================
# Model：登録入力用
# ======================================================
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 BusinessException(
                error_code="ACCOUNT_CODE_INVALID",
                message="科目コードは数字のみで入力してください"
            )
        if len(v) > 20:
            raise BusinessException(
                error_code="ACCOUNT_CODE_TOO_LONG",
                message="科目コードは20文字以内で入力してください"
            )
        return v

    @field_validator("account_name")
    @classmethod
    def validate_name(cls, v: str):
        if not v.strip():
            raise BusinessException(
                error_code="ACCOUNT_NAME_EMPTY",
                message="科目名を入力してください"
            )
        if len(v) > 100:
            raise BusinessException(
                error_code="ACCOUNT_NAME_TOO_LONG",
                message="科目名は100文字以内で入力してください"
            )
        return v


# ======================================================
# GET：科目一覧取得
# ======================================================
@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
        """)
        rows = cur.fetchall()

        if not rows:
            raise BusinessException(
                error_code="ACCOUNT_NOT_FOUND",
                message="科目が登録されていません"
            )

        return rows


# ======================================================
# POST：科目登録
# ======================================================
@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:
        raise BusinessException(
            error_code="ACCOUNT_DUPLICATE",
            message="この科目コードは既に登録されています"
        )

    except StringDataRightTruncation:
        raise BusinessException(
            error_code="ACCOUNT_VALUE_TOO_LONG",
            message="入力文字数が制限を超えています"
        )

    except CheckViolation:
        raise BusinessException(
            error_code="ACCOUNT_VALUE_INVALID",
            message="入力値が不正です"
        )
