"""
月次給与計算API (Monthly Payroll Calculation API)
"""
from fastapi import APIRouter, HTTPException, status
from typing import List
from datetime import datetime
from . import schemas
from .service import PayrollCalculationService
from ...core.database import get_connection


router = APIRouter(prefix="/payroll/calculation", tags=["Payroll - Calculation"])


@router.post("/calculate", response_model=schemas.MonthlyPayroll, status_code=status.HTTP_201_CREATED)
def calculate_payroll(request: schemas.PayrollCalculationRequest):
    """給与を計算して保存"""
    
    # 既存のデータを確認
    with get_connection() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT payroll_id FROM monthly_payroll 
                WHERE employee_id = %s 
                AND payroll_year = %s 
                AND payroll_month = %s
                """,
                (request.employee_id, request.payroll_year, request.payroll_month)
            )
            existing = cur.fetchone()
            
            if existing:
                raise HTTPException(
                    status_code=400, 
                    detail="この従業員の指定月の給与データは既に存在します"
                )
    
    # 給与計算を実行
    try:
        calc_result = PayrollCalculationService.calculate_payroll(
            employee_id=request.employee_id,
            payroll_year=request.payroll_year,
            payroll_month=request.payroll_month,
            working_days=request.working_days,
            working_hours=request.working_hours,
            overtime_hours=request.overtime_hours,
            holiday_hours=request.holiday_hours,
            late_hours=request.late_hours,
            absent_days=request.absent_days,
            payment_date=request.payment_date,
            other_allowance=request.other_allowance,
            resident_tax=request.resident_tax,
            other_deduction=request.other_deduction,
            calc_income_tax=request.calc_income_tax,
            calc_social_insurance=request.calc_social_insurance
        )
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    
    # 結果をデータベースに保存
    with get_connection() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                INSERT INTO monthly_payroll (
                    employee_id, payroll_year, payroll_month, payment_date, status,
                    working_days, working_hours, overtime_hours, holiday_hours, late_hours, absent_days,
                    base_salary, overtime_pay, holiday_pay, commute_allowance, other_allowance, total_payment,
                    health_insurance, care_insurance, pension_insurance, employment_insurance, 
                    income_tax, resident_tax, other_deduction, total_deduction,
                    net_payment, calculated_at, calculated_by
                ) VALUES (
                    %s, %s, %s, %s, %s,
                    %s, %s, %s, %s, %s, %s,
                    %s, %s, %s, %s, %s, %s,
                    %s, %s, %s, %s,
                    %s, %s, %s, %s,
                    %s, %s, %s
                )
                RETURNING *
                """,
                (
                    calc_result["employee_id"], calc_result["payroll_year"], calc_result["payroll_month"],
                    calc_result["payment_date"], calc_result["status"],
                    calc_result["working_days"], calc_result["working_hours"], calc_result["overtime_hours"],
                    calc_result["holiday_hours"], calc_result["late_hours"], calc_result["absent_days"],
                    calc_result["base_salary"], calc_result["overtime_pay"], calc_result["holiday_pay"],
                    calc_result["commute_allowance"], calc_result["other_allowance"], calc_result["total_payment"],
                    calc_result["health_insurance"], calc_result["care_insurance"], 
                    calc_result["pension_insurance"], calc_result["employment_insurance"],
                    calc_result["income_tax"], calc_result["resident_tax"], calc_result["other_deduction"],
                    calc_result["total_deduction"],
                    calc_result["net_payment"], datetime.now(), calc_result["calculated_by"]
                )
            )
            result = cur.fetchone()
            conn.commit()
            return result


@router.get("/", response_model=List[schemas.MonthlyPayroll])
def get_payrolls(payroll_year: int = None, payroll_month: int = None, employee_id: int = None):
    """給与計算一覧を取得"""
    conditions = []
    params = []
    
    if payroll_year:
        conditions.append("payroll_year = %s")
        params.append(payroll_year)
    
    if payroll_month:
        conditions.append("payroll_month = %s")
        params.append(payroll_month)
    
    if employee_id:
        conditions.append("employee_id = %s")
        params.append(employee_id)
    
    where_clause = " AND ".join(conditions) if conditions else "1=1"
    
    with get_connection() as conn:
        with conn.cursor() as cur:
            cur.execute(
                f"""
                SELECT * FROM monthly_payroll 
                WHERE {where_clause}
                ORDER BY payroll_year DESC, payroll_month DESC, employee_id
                """,
                params
            )
            return cur.fetchall()


@router.get("/{payroll_id}", response_model=schemas.MonthlyPayrollWithDetails)
def get_payroll(payroll_id: int):
    """給与計算詳細を取得"""
    with get_connection() as conn:
        with conn.cursor() as cur:
            cur.execute("SELECT * FROM monthly_payroll WHERE payroll_id = %s", (payroll_id,))
            payroll = cur.fetchone()
            
            if not payroll:
                raise HTTPException(status_code=404, detail="給与データが見つかりません")
            
            cur.execute(
                "SELECT * FROM payroll_details WHERE payroll_id = %s ORDER BY detail_id",
                (payroll_id,)
            )
            details = cur.fetchall()
            
            return {**payroll, "details": details}


@router.put("/{payroll_id}", response_model=schemas.MonthlyPayroll)
def update_payroll(payroll_id: int, request: schemas.MonthlyPayrollUpdate):
    """給与データを更新（再計算は行わない）"""
    update_data = request.model_dump(exclude_unset=True)
    if not update_data:
        raise HTTPException(status_code=400, detail="更新するデータがありません")
    
    set_clause = ", ".join([f"{key} = %s" for key in update_data.keys()])
    values = list(update_data.values()) + [payroll_id]
    
    with get_connection() as conn:
        with conn.cursor() as cur:
            cur.execute(
                f"UPDATE monthly_payroll SET {set_clause} WHERE payroll_id = %s RETURNING *",
                values,
            )
            result = cur.fetchone()
            if not result:
                raise HTTPException(status_code=404, detail="給与データが見つかりません")
            conn.commit()
            return result


@router.post("/{payroll_id}/recalculate", response_model=schemas.MonthlyPayroll)
def recalculate_payroll(payroll_id: int, request: schemas.RecalculateRequest = None):
    """給与を再計算"""
    if request is None:
        request = schemas.RecalculateRequest()
    with get_connection() as conn:
        with conn.cursor() as cur:
            # 既存データを取得
            cur.execute("SELECT * FROM monthly_payroll WHERE payroll_id = %s", (payroll_id,))
            existing = cur.fetchone()
            
            if not existing:
                raise HTTPException(status_code=404, detail="給与データが見つかりません")
            
            if existing["status"] == "approved":
                raise HTTPException(status_code=400, detail="承認済みの給与は再計算できません")
            
            # 再計算
            try:
                calc_result = PayrollCalculationService.calculate_payroll(
                    employee_id=existing["employee_id"],
                    payroll_year=existing["payroll_year"],
                    payroll_month=existing["payroll_month"],
                    working_days=existing["working_days"],
                    working_hours=existing["working_hours"],
                    overtime_hours=existing["overtime_hours"],
                    holiday_hours=existing["holiday_hours"],
                    late_hours=existing["late_hours"],
                    absent_days=existing["absent_days"],
                    payment_date=existing["payment_date"],
                    other_allowance=existing["other_allowance"],
                    resident_tax=existing["resident_tax"],
                    other_deduction=existing["other_deduction"],
                    calculated_by="recalculated",
                    calc_income_tax=request.calc_income_tax,
                    calc_social_insurance=request.calc_social_insurance
                )
            except ValueError as e:
                raise HTTPException(status_code=400, detail=str(e))
            
            # 更新
            cur.execute(
                """
                UPDATE monthly_payroll SET
                    base_salary = %s, overtime_pay = %s, holiday_pay = %s,
                    commute_allowance = %s, total_payment = %s,
                    health_insurance = %s, pension_insurance = %s, employment_insurance = %s,
                    income_tax = %s, total_deduction = %s, net_payment = %s,
                    calculated_at = %s, calculated_by = %s
                WHERE payroll_id = %s
                RETURNING *
                """,
                (
                    calc_result["base_salary"], calc_result["overtime_pay"], calc_result["holiday_pay"],
                    calc_result["commute_allowance"], calc_result["total_payment"],
                    calc_result["health_insurance"], calc_result["pension_insurance"], 
                    calc_result["employment_insurance"],
                    calc_result["income_tax"], calc_result["total_deduction"], calc_result["net_payment"],
                    datetime.now(), calc_result["calculated_by"],
                    payroll_id
                )
            )
            result = cur.fetchone()
            conn.commit()
            return result


@router.post("/{payroll_id}/approve", response_model=schemas.MonthlyPayroll)
def approve_payroll(payroll_id: int, request: schemas.PayrollApprovalRequest):
    """給与を承認"""
    with get_connection() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                UPDATE monthly_payroll 
                SET status = 'approved', approved_at = %s, approved_by = %s
                WHERE payroll_id = %s AND status = 'calculated'
                RETURNING *
                """,
                (datetime.now(), request.approved_by, payroll_id)
            )
            result = cur.fetchone()
            
            if not result:
                raise HTTPException(
                    status_code=400, 
                    detail="給与データが見つからないか、既に承認されています"
                )
            
            conn.commit()
            return result


@router.delete("/{payroll_id}")
def delete_payroll(payroll_id: int):
    """給与データを削除"""
    with get_connection() as conn:
        with conn.cursor() as cur:
            # ステータス確認
            cur.execute(
                "SELECT status FROM monthly_payroll WHERE payroll_id = %s",
                (payroll_id,)
            )
            payroll = cur.fetchone()
            
            if not payroll:
                raise HTTPException(status_code=404, detail="給与データが見つかりません")
            
            if payroll["status"] == "approved":
                raise HTTPException(status_code=400, detail="承認済みの給与は削除できません")
            
            cur.execute("DELETE FROM monthly_payroll WHERE payroll_id = %s", (payroll_id,))
            conn.commit()
            
            return {"message": "給与データを削除しました", "payroll_id": payroll_id}
