#!/usr/bin/env python3
"""
NULL値チェック・デフォルト値テストスクリプト
"""

import os
import psycopg2
import logging

# ログ設定
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# データベース設定
OLD_ROGDB_CONFIG = {
    'host': os.getenv('OLD_ROGDB_HOST', 'postgres-db'),
    'database': os.getenv('OLD_ROGDB_NAME', 'old_rogdb'),
    'user': os.getenv('OLD_ROGDB_USER', 'admin'),
    'password': os.getenv('OLD_ROGDB_PASSWORD', 'admin123456'),
    'port': int(os.getenv('OLD_ROGDB_PORT', 5432))
}

ROGDB_CONFIG = {
    'host': os.getenv('ROGDB_HOST', 'postgres-db'),
    'database': os.getenv('ROGDB_NAME', 'rogdb'),
    'user': os.getenv('ROGDB_USER', 'admin'),
    'password': os.getenv('ROGDB_PASSWORD', 'admin123456'),
    'port': int(os.getenv('ROGDB_PORT', 5432))
}

def check_null_values():
    """NULL値の問題を事前チェック"""
    try:
        old_conn = psycopg2.connect(**OLD_ROGDB_CONFIG)
        new_conn = psycopg2.connect(**ROGDB_CONFIG)
        
        old_conn.autocommit = True
        new_conn.autocommit = True
        
        old_cursor = old_conn.cursor()
        new_cursor = new_conn.cursor()
        
        # 共通テーブル取得
        old_cursor.execute("""
            SELECT table_name FROM information_schema.tables 
            WHERE table_schema = 'public' AND table_name LIKE 'rog_%'
        """)
        old_tables = [row[0] for row in old_cursor.fetchall()]
        
        new_cursor.execute("""
            SELECT table_name FROM information_schema.tables 
            WHERE table_schema = 'public' AND table_name LIKE 'rog_%'
        """)
        new_tables = [row[0] for row in new_cursor.fetchall()]
        
        common_tables = list(set(old_tables) & set(new_tables))
        
        logger.info(f"チェック対象テーブル: {len(common_tables)}個")
        
        null_issues = {}
        
        for table_name in common_tables:
            logger.info(f"=== {table_name} NULL値チェック ===")
            
            # 新しいDBのNOT NULL制約確認
            new_cursor.execute("""
                SELECT column_name, is_nullable, column_default
                FROM information_schema.columns 
                WHERE table_name = %s AND table_schema = 'public'
                AND is_nullable = 'NO'
                ORDER BY ordinal_position
            """, (table_name,))
            
            not_null_columns = new_cursor.fetchall()
            
            if not not_null_columns:
                logger.info(f"  NOT NULL制約なし")
                continue
            
            logger.info(f"  NOT NULL制約カラム: {[col[0] for col in not_null_columns]}")
            
            # 古いDBのNULL値チェック
            for col_name, is_nullable, default_val in not_null_columns:
                try:
                    # PostgreSQL予約語とcamelCaseカラムのクォート処理
                    reserved_words = ['group', 'like', 'order', 'user', 'table', 'index', 'where', 'from', 'select']
                    quoted_col = f'"{col_name}"' if (col_name.lower() in reserved_words or any(c.isupper() for c in col_name)) else col_name
                    
                    # カラム存在チェック
                    old_cursor.execute("""
                        SELECT COUNT(*) FROM information_schema.columns 
                        WHERE table_name = %s AND column_name = %s AND table_schema = 'public'
                    """, (table_name, col_name))
                    
                    if old_cursor.fetchone()[0] == 0:
                        logger.warning(f"    ⚠️  {col_name}: 古いDBに存在しないカラム")
                        continue
                    
                    old_cursor.execute(f"""
                        SELECT COUNT(*) FROM {table_name} 
                        WHERE {quoted_col} IS NULL
                    """)
                    
                    null_count = old_cursor.fetchone()[0]
                    
                    if null_count > 0:
                        logger.warning(f"    ⚠️  {col_name}: {null_count}件のNULL値あり (デフォルト: {default_val})")
                        
                        if table_name not in null_issues:
                            null_issues[table_name] = []
                        null_issues[table_name].append((col_name, null_count, default_val))
                    else:
                        logger.info(f"    ✅ {col_name}: NULL値なし")
                        
                except Exception as e:
                    logger.error(f"    ❌ {col_name}: チェックエラー: {e}")
        
        # サマリー
        if null_issues:
            logger.warning("=" * 60)
            logger.warning("NULL値問題のあるテーブル:")
            for table, issues in null_issues.items():
                logger.warning(f"  {table}:")
                for col, count, default in issues:
                    logger.warning(f"    - {col}: {count}件 (デフォルト: {default})")
        else:
            logger.info("✅ NULL値の問題はありません")
        
        old_cursor.close()
        new_cursor.close()
        old_conn.close()
        new_conn.close()
        
        return null_issues
        
    except Exception as e:
        logger.error(f"❌ NULL値チェックエラー: {e}")
        return {}

def suggest_default_values(null_issues):
    """デフォルト値の提案"""
    if not null_issues:
        return
    
    logger.info("=" * 60)
    logger.info("推奨デフォルト値設定:")
    
    for table_name, issues in null_issues.items():
        logger.info(f"  '{table_name}': {{")
        for col_name, count, default in issues:
            # データ型に基づくデフォルト値推測
            if 'trial' in col_name.lower() or 'is_' in col_name.lower():
                suggested = 'False'
            elif 'public' in col_name.lower():
                suggested = 'True'
            elif 'name' in col_name.lower() or 'description' in col_name.lower():
                suggested = "''"
            elif 'order' in col_name.lower() or 'sort' in col_name.lower():
                suggested = '0'
            else:
                suggested = 'None  # 要確認'
            
            logger.info(f"    '{col_name}': {suggested},  # {count}件のNULL")
        logger.info("  },")

def main():
    logger.info("=" * 60)
    logger.info("NULL値チェック・デフォルト値提案スクリプト")
    logger.info("=" * 60)
    
    null_issues = check_null_values()
    suggest_default_values(null_issues)
    
    logger.info("=" * 60)
    logger.info("チェック完了")
    logger.info("=" * 60)

if __name__ == "__main__":
    main()
