from fastapi import APIRouter, UploadFile, File, HTTPException, Form
from fastapi.responses import JSONResponse
from typing import List, Optional
from pydantic import BaseModel
from decimal import Decimal
import openpyxl
from io import BytesIO
from app.core.database import get_connection

router = APIRouter(prefix="/payroll/settings/standard-remuneration", tags=["standard_remuneration"])


class StandardRemunerationRow(BaseModel):
    grade: str
    monthly_amount: Decimal
    salary_from: Decimal
    salary_to: Optional[Decimal]
    health_insurance_no_care: Decimal
    health_insurance_with_care: Decimal
    pension_insurance: Decimal


@router.get("/years")
async def get_years():
    """登録済みの年度一覧を取得"""
    try:
        with get_connection() as conn:
            with conn.cursor() as cur:
                cur.execute("SELECT DISTINCT rate_year FROM standard_remuneration ORDER BY rate_year DESC")
                rows = cur.fetchall()
                years = [row["rate_year"] for row in rows]
        return years
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("")
async def get_standard_remuneration(year: int, prefecture: Optional[str] = None):
    """指定された年度・都道府県の標準報酬月額表を取得"""
    try:
        with get_connection() as conn:
            with conn.cursor() as cur:
                if prefecture:
                    query = """
                        SELECT rate_year, prefecture, grade, monthly_amount, salary_from, salary_to,
                               health_insurance_no_care, health_insurance_with_care, pension_insurance
                        FROM standard_remuneration
                        WHERE rate_year = %s AND prefecture = %s
                        ORDER BY prefecture, 
                                 CASE WHEN grade ~ '^[0-9]+$' THEN CAST(grade AS INTEGER) ELSE 999 END,
                                 grade
                    """
                    cur.execute(query, (year, prefecture))
                else:
                    query = """
                        SELECT rate_year, prefecture, grade, monthly_amount, salary_from, salary_to,
                               health_insurance_no_care, health_insurance_with_care, pension_insurance
                        FROM standard_remuneration
                        WHERE rate_year = %s
                        ORDER BY prefecture, 
                                 CASE WHEN grade ~ '^[0-9]+$' THEN CAST(grade AS INTEGER) ELSE 999 END,
                                 grade
                    """
                    cur.execute(query, (year,))
                
                rows = cur.fetchall()
        
        result = []
        for row in rows:
            result.append({
                "rate_year": row["rate_year"],
                "prefecture": row["prefecture"],
                "grade": row["grade"],
                "monthly_amount": row["monthly_amount"],
                "salary_from": row["salary_from"],
                "salary_to": row["salary_to"],
                "health_insurance_no_care": row["health_insurance_no_care"],
                "health_insurance_with_care": row["health_insurance_with_care"],
                "pension_insurance": row["pension_insurance"]
            })
        
        return result
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/import")
async def import_standard_remuneration(
    file: UploadFile = File(...),
    prefecture: str = Form(...)
):
    """Excelファイルから標準報酬月額表をインポート（年度はA1セルから自動取得）"""
    try:
        # Excelファイルを読み込み
        contents = await file.read()
        wb = openpyxl.load_workbook(BytesIO(contents), data_only=True)
        
        # 指定された都道府県のシートを取得
        if prefecture not in wb.sheetnames:
            raise HTTPException(
                status_code=400, 
                detail=f"シート '{prefecture}' が見つかりません。利用可能なシート: {', '.join(wb.sheetnames)}"
            )
        
        ws = wb[prefecture]
        
        # A1セルから年度を取得
        # 例: "令和7年3月分（4月納付分）からの健康保険・厚生年金保険の保険料額表（東京都）"
        a1_value = ws["A1"].value
        if not a1_value:
            raise HTTPException(status_code=400, detail="A1セルに年度情報がありません")
        
        # 令和年号から西暦年度を計算（例: 令和7年 = 2025年度）
        import re
        match = re.search(r'令和(\d+)年', str(a1_value))
        if match:
            reiwa_year = int(match.group(1))
            rate_year = 2018 + reiwa_year  # 令和元年 = 2019年
        else:
            # 西暦が直接記載されている場合
            match = re.search(r'(\d{4})年', str(a1_value))
            if match:
                rate_year = int(match.group(1))
            else:
                raise HTTPException(
                    status_code=400, 
                    detail=f"A1セルから年度を抽出できません: {a1_value}"
                )
        
        # 第9行からメタデータ（保険料率）を抽出
        metadata = {}
        try:
            row9 = list(ws.iter_rows(min_row=9, max_row=9, values_only=True))[0]
            # F9, H9, J9 (インデックス 5, 7, 9) から値を取得
            health_no_care_rate = row9[5] if len(row9) > 5 else None  # F9
            health_with_care_rate = row9[7] if len(row9) > 7 else None  # H9
            pension_rate = row9[9] if len(row9) > 9 else None  # J9
            
            print(f"[メタデータ] 第9行: F9={health_no_care_rate}, H9={health_with_care_rate}, J9={pension_rate}")
            
            # パーセンテージをクリーニング（文字列から%を削除）
            def clean_percentage(val):
                if val is None:
                    return None
                val_str = str(val).strip()
                val_str = val_str.replace('%', '').replace('％', '')
                try:
                    return float(val_str)
                except:
                    return None
            
            metadata = {
                'health_no_care_rate': clean_percentage(health_no_care_rate),
                'health_with_care_rate': clean_percentage(health_with_care_rate),
                'pension_rate': clean_percentage(pension_rate),
                'source': str(a1_value) if a1_value else None  # A1セルの内容を追加
            }
            print(f"[メタデータ クリーニング後] {metadata}")
        except Exception as e:
            print(f"[警告] メタデータ抽出エラー: {e}")
            metadata = {}
        
        # データを抽出（12行目から開始）
        data_rows = []
        errors = []
        rows_read = []
        
        # まずヘッダー行を確認（11行目）
        header_row = list(ws.iter_rows(min_row=11, max_row=11, values_only=True))[0]
        # ヘッダー行の全列を表示
        header_debug = f"ヘッダー(11行目): {list(header_row)}"
        errors.append(header_debug)
        
        # min_row=12で12行目から読み取りを開始
        # enumerate()はイテレータの要素番号なので、start=0にして、実際の行番号は手動で計算
        for idx, row in enumerate(ws.iter_rows(min_row=12, values_only=True)):
            row_idx = 12 + idx  # 実際のExcel行番号
            # 最初の1行だけ全列を記録（デバッグ用）
            if idx == 0:
                row_debug = f"Row {row_idx} (最初のデータ行): {list(row)}"
            else:
                row_debug = f"Row {row_idx}: {row[:10]}"
            rows_read.append(row_debug)
            
            # 等級が空の場合は終了
            if not row[0]:
                break
            
            try:
                grade = str(row[0]).strip()
                
                # 各値を取得し、Noneや空白を処理
                def clean_value(val, field_name=""):
                    # 允许 '-', '－', '―', 'ー', '−', '' 视为 0
                    if val is None:
                        return 0
                    if isinstance(val, (int, float)):
                        return val
                    if isinstance(val, str):
                        val = val.strip()
                        if val in ('', '-', '－', '―', 'ー', '−'):
                            return 0
                        val = val.replace('円', '').replace('未満', '').replace('以上', '')
                        val = val.replace(',', '').replace('，', '')
                        val = val.translate(str.maketrans('０１２３４５６７８９', '0123456789'))
                        if val == '':
                            return 0
                        return val
                    return val
                
                # デバッグ用に元のデータとclean_value结果を保存
                raw_data = {
                    'col0_grade': row[0] if len(row) > 0 else None,
                    'col1': row[1] if len(row) > 1 else None,
                    'col2': row[2] if len(row) > 2 else None,
                    'col3': row[3] if len(row) > 3 else None,
                    'col4': row[4] if len(row) > 4 else None,
                    'col5': row[5] if len(row) > 5 else None,
                    'col6': row[6] if len(row) > 6 else None,
                    'col7': row[7] if len(row) > 7 else None,
                }
                # 记录清洗后的值
                cleaned_data = {
                    'grade': clean_value(row[0]) if len(row) > 0 else None,
                    'monthly_amount': clean_value(row[1]) if len(row) > 1 else None,
                    'salary_from': clean_value(row[2]) if len(row) > 2 else None,
                    'salary_to': clean_value(row[3]) if len(row) > 3 else None,
                    'health_no_care': clean_value(row[4]) if len(row) > 4 else None,
                    'health_with_care': clean_value(row[5]) if len(row) > 5 else None,
                    'pension': clean_value(row[6]) if len(row) > 6 else None,
                }
                # 追加调试信息
                errors.append(f"行{row_idx}: 原始数据={raw_data}, 清洗後={cleaned_data}")
                
                # 報酬月額範囲の処理
                # 複数のパターンに対応:
                # パターンA: 列2に範囲（"58,000円～63,000円"）
                # パターンB: 列2=下限, 列3=「～」, 列4=上限
                # パターンC: 列2=下限, 列3=上限
                
                monthly_amount = clean_value(row[1], 'monthly_amount')
                
                # 列2と列3の内容をチェック
                col2_raw = str(row[2]) if len(row) > 2 and row[2] is not None else ''
                col3_raw = str(row[3]) if len(row) > 3 and row[3] is not None else ''
                col2_cleaned = col2_raw.strip()
                col3_cleaned = col3_raw.strip()
                
                # パターン判定：
                # パターンA: col2 = '～', col3 = 数値 → [grade, monthly, ~, range_to, health_no_full, health_no_half, health_with_full, health_with_half, ...]
                # パターンB: col2 = 数値, col3 = '～' → [grade, monthly, range_from, ~, range_to, health_no_full, health_no_half, health_with_full, health_with_half, ...]
                # パターンC: col2 = 数値, col3 = 数値 → [grade, monthly, range_from, range_to, health_no_full, health_no_half, health_with_full, health_with_half, ...]
                
                if col2_cleaned in ('～', '〜', '-'):
                    # パターンA: 列2=「～」, 列3=上限値
                    salary_from = 0  # または前の行から取得
                    salary_to = clean_value(row[3], 'salary_to')
                    # 保険料は列4以降
                    health_no_care = clean_value(row[4] if len(row) > 4 else None, 'health_no_care')
                    health_with_care = clean_value(row[6] if len(row) > 6 else None, 'health_with_care')
                    
                    # デバッグ: row全体の長さとrow[8]の値を記録
                    print(f"[デバッグ パターンA] 行{row_idx}: len(row)={len(row)}, row全体={list(row)}")
                    print(f"  row[8]={row[8] if len(row) > 8 else 'N/A (行が短い)'}")
                    
                    pension = clean_value(row[8] if len(row) > 8 else None, 'pension')
                    if pension == 0:
                        print(f"  ⚠️ 警告: ペンション値が0です。row[8]の元データ = {row[8] if len(row) > 8 else 'N/A'}")
                    print(f"  clean_value後: pension={pension}, type={type(pension)}")
                    
                elif col3_cleaned in ('～', '〜', '-'):
                    # パターンB: 列2=下限, 列3=「～」, 列4=上限
                    salary_from = clean_value(row[2], 'salary_from')
                    salary_to = clean_value(row[4] if len(row) > 4 else None, 'salary_to')
                    # 保険料は列5以降
                    health_no_care = clean_value(row[5] if len(row) > 5 else None, 'health_no_care')
                    health_with_care = clean_value(row[7] if len(row) > 7 else None, 'health_with_care')
                    pension = clean_value(row[9] if len(row) > 9 else None, 'pension')
                    
                else:
                    # パターンC: 列2=下限、列3=上限の数値パターン
                    salary_from = clean_value(row[2], 'salary_from')
                    salary_to = clean_value(row[3], 'salary_to')
                    # 保険料は列4以降
                    health_no_care = clean_value(row[4] if len(row) > 4 else None, 'health_no_care')
                    health_with_care = clean_value(row[6] if len(row) > 6 else None, 'health_with_care')
                    pension = clean_value(row[8] if len(row) > 8 else None, 'pension')
                
                # 必須フィールドのチェック（詳細なエラーメッセージ）
                missing_fields = []
                if monthly_amount is None:
                    missing_fields.append(f"標準報酬月額(列2)={repr(raw_data['col1'])}")
                if salary_from is None:
                    missing_fields.append(f"報酬月額下限={repr(raw_data['col2'])}")
                if health_no_care is None:
                    missing_fields.append(f"健保(介護なし)={repr(raw_data.get('col4') or raw_data.get('col3'))}")
                if health_with_care is None:
                    missing_fields.append(f"健保(介護あり)={repr(raw_data.get('col5') or raw_data.get('col4'))}")
                if pension is None:
                    missing_fields.append(f"厚生年金={repr(raw_data.get('col6') or raw_data.get('col5'))}")
                
                if missing_fields:
                    errors.append(f"行{row_idx}: 必須フィールドが空: {', '.join(missing_fields)}")
                    continue
                
                # Decimal変換（より詳細なエラー処理）
                try:
                    monthly_amount = Decimal(str(monthly_amount))
                except Exception as e:
                    errors.append(f"行{row_idx}: 標準報酬月額の変換エラー: {repr(raw_data['col1'])} -> {e}")
                    continue
                
                try:
                    salary_from = Decimal(str(salary_from))
                except Exception as e:
                    errors.append(f"行{row_idx}: 報酬月額下限の変換エラー: {repr(raw_data['col2'])} -> {e}")
                    continue
                
                try:
                    salary_to = Decimal(str(salary_to)) if salary_to is not None else None
                except Exception as e:
                    errors.append(f"行{row_idx}: 報酬月額上限の変換エラー: 範囲から抽出または{repr(raw_data.get('col3'))} -> {e}")
                    continue
                
                try:
                    health_no_care = Decimal(str(health_no_care))
                except Exception as e:
                    errors.append(f"行{row_idx}: 健保(介護なし)の変換エラー: {repr(health_no_care)} (元データ列={raw_data}) -> {e}")
                    continue
                
                try:
                    health_with_care = Decimal(str(health_with_care))
                except Exception as e:
                    errors.append(f"行{row_idx}: 健保(介護あり)の変換エラー: {repr(health_with_care)} (元データ列={raw_data}) -> {e}")
                    continue
                
                try:
                    pension = Decimal(str(pension))
                except Exception as e:
                    errors.append(f"行{row_idx}: 厚生年金の変換エラー: {repr(pension)} (元データ列={raw_data}) -> {e}")
                    continue
                
                data_rows.append((
                    rate_year, prefecture, grade, monthly_amount, salary_from, salary_to,
                    health_no_care, health_with_care, pension
                ))
                
            except Exception as e:
                errors.append(f"行{row_idx}: 予期しないエラー: {type(e).__name__}: {str(e)}")
                continue
        
        if not data_rows:
            error_msg = "有効なデータが見つかりませんでした"
            if errors:
                error_msg += "\n\nエラー詳細:\n" + "\n".join(errors[:15])
            if rows_read:
                error_msg += "\n\n読み込んだ行:\n" + "\n".join(rows_read[:10])
            raise HTTPException(status_code=400, detail=error_msg)
        
        # データベースに保存
        with get_connection() as conn:
            with conn.cursor() as cur:
                # 既存データを削除
                cur.execute(
                    "DELETE FROM standard_remuneration WHERE rate_year = %s AND prefecture = %s",
                    (rate_year, prefecture)
                )
                
                # 新しいデータを挿入
                insert_query = """
                    INSERT INTO standard_remuneration 
                    (rate_year, prefecture, grade, monthly_amount, salary_from, salary_to,
                     health_insurance_no_care, health_insurance_with_care, pension_insurance)
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
                """
                
                cur.executemany(insert_query, data_rows)
                conn.commit()
                imported_count = len(data_rows)
        
        return {
            "message": "インポートが完了しました",
            "year": rate_year,
            "prefecture": prefecture,
            "imported_count": imported_count,
            "source": a1_value,
            "metadata": metadata,
            "debug_info": {
                "total_rows_read": len(rows_read),
                "first_rows_sample": rows_read[:3],
                "a1_value_debug": f"A1セル内容: {a1_value}"
            }
        }
        
    except ValueError as e:
        raise HTTPException(status_code=400, detail=f"年度は数値で入力してください: {str(e)}")
    except Exception as e:
        error_detail = {
            "error": str(e),
            "error_type": type(e).__name__,
            "rows_read_count": len(rows_read) if 'rows_read' in locals() else 0,
            "first_rows_sample": rows_read[:3] if 'rows_read' in locals() else []
        }
        raise HTTPException(status_code=500, detail=error_detail)


@router.delete("")
async def delete_standard_remuneration(year: int, prefecture: str):
    """指定された年度・都道府県の標準報酬月額表を削除"""
    try:
        with get_connection() as conn:
            with conn.cursor() as cur:
                cur.execute(
                    "DELETE FROM standard_remuneration WHERE rate_year = %s AND prefecture = %s",
                    (year, prefecture)
                )
                deleted_count = cur.rowcount
                conn.commit()
        
        return {
            "message": "削除しました",
            "year": year,
            "prefecture": prefecture,
            "deleted_count": deleted_count
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.delete("/all")
async def delete_all_standard_remuneration():
    """すべての標準報酬月額表データを削除"""
    try:
        with get_connection() as conn:
            with conn.cursor() as cur:
                cur.execute("DELETE FROM standard_remuneration")
                deleted_count = cur.rowcount
                conn.commit()
        
        return {
            "message": "すべてのデータを削除しました",
            "deleted_count": deleted_count
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.delete("/year/{year}")
async def delete_standard_remuneration_by_year(year: int):
    """指定された年度の標準報酬月額表データをすべて削除"""
    try:
        with get_connection() as conn:
            with conn.cursor() as cur:
                cur.execute(
                    "DELETE FROM standard_remuneration WHERE rate_year = %s",
                    (year,)
                )
                deleted_count = cur.rowcount
                conn.commit()
        
        return {
            "message": f"{year}年度のデータを削除しました",
            "year": year,
            "deleted_count": deleted_count
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
