from flask import Flask, request, jsonify, render_template, send_from_directory
import base64
from pydub import AudioSegment
import os
import shutil
import requests
import tempfile
import json
from process import AudioProcessor
from transcription import TranscriptionMaker
from analyze import TextAnalyzer

process = AudioProcessor()
transcripter = TranscriptionMaker()
app = Flask(__name__)

# GASのエンドポイントURL
GAS_URL = "https://script.google.com/macros/s/AKfycbwR2cnMKVU1AxoT9NDaeZaNUaTiwRX64Ul0sH0AU4ccP49Byph-TpxtM_Lwm4G9zLnuYA/exec"

users = []  # 選択されたユーザーのリスト
all_users = []  # 利用可能なすべてのユーザーのリスト
transcription_text = ""
harassment_keywords = [
    "バカ", "馬鹿", "アホ", "死ね", "クソ", "うざい",
    "きもい", "キモい", "ブス", "デブ", "ハゲ",
    "セクハラ", "パワハラ", "モラハラ"
]
total_audio = ""


@app.route('/index', methods=['GET', 'POST'])
def index():
    return render_template('index.html', users=users)

# フィードバック画面(テンプレート: feedback.html)
@app.route('/feedback', methods=['GET', 'POST'])
def feedback():
    return render_template('feedback.html')

# 会話詳細画面(テンプレート: talkDetail.html)
@app.route('/talk_detail', methods=['GET', 'POST'])
def talk_detail():
    return render_template('talkDetail.html')

# 音声登録画面(テンプレート: userRegister.html)
@app.route('/userregister', methods=['GET', 'POST'])
def userregister():
    return render_template('userRegister.html')

# 人数確認
@app.route('/confirm', methods=['GET'])
def confirm():
    global all_users
    # 最新のユーザーリストを取得
    try:
        update_all_users()
    except Exception as e:
        print(f"ユーザーリストの更新エラー: {str(e)}")
    return jsonify({'members': users, 'all_members': all_users}), 200

# リセット画面(テンプレート: reset.html)
@app.route('/reset_html', methods=['GET', 'POST']) 
def reset_html():
    return render_template('reset.html')

# メンバー削除&累積音声削除
@app.route('/reset_member', methods=['GET', 'POST'])
def reset_member():
    global users
    global total_audio
    global transcription_text
    
    # 一時ディレクトリのクリーンアップ
    if total_audio:
        process.delete_files_in_directory(total_audio)
    process.delete_files_in_directory('/tmp/data/transcription_audio')
    
    # 書き起こしテキストの削除
    if os.path.exists(transcription_text):
        try:
            os.remove(transcription_text)
            print(f"{transcription_text} を削除しました。")
        except Exception as e:
            print(f"ファイル削除中にエラーが発生しました: {e}")
    
    transcription_text = ""
    
    try:
        data = request.get_json()
        if not data or "names" not in data:
            return jsonify({"status": "error", "message": "Invalid request body"}), 400

        names = data.get("names", [])
        
        # GASからファイルを削除
        for name in names:
            try:
                delete_from_cloud(f"{name}.wav")
                print(f"クラウドから {name}.wav を削除しました。")
            except Exception as e:
                print(f"クラウド削除中にエラーが発生しました: {e}")
                return jsonify({"status": "error", "message": f"Failed to delete {name} from cloud: {e}"}), 500

        # usersリストから削除するユーザーを除外
        users = [u for u in users if u not in names]
        
        # 全ユーザーリストの更新
        update_all_users()

        return jsonify({"status": "success", "message": "Members deleted successfully", "users": users}), 200

    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        return jsonify({"status": "error", "message": f"Internal server error: {e}"}), 500

# 書き起こし作成エンドポイント
@app.route('/transcription', methods=['GET', 'POST'])
def transcription():
    global transcription_text
    global total_audio
    
    if not os.path.exists(transcription_text) or not transcription_text:
        try: 
            if not total_audio or not os.path.exists(total_audio):
                return jsonify({"error": "No audio segments provided"}), 400
            transcription_text = transcripter.create_transcription(total_audio)
            print("transcription")
            print(transcription_text)
        except Exception as e:
            return jsonify({"error": str(e)}), 500
    
    try:
        with open(transcription_text, 'r', encoding='utf-8') as file:
            file_content = file.read()
            print(file_content)
            return jsonify({'transcription': file_content}), 200
    except FileNotFoundError:
        return jsonify({"error": "Transcription file not found"}), 404
    except Exception as e:
        return jsonify({"error": f"Unexpected error: {str(e)}"}), 500

# AI分析エンドポイント
@app.route('/analyze', methods=['GET', 'POST'])
def analyze():
    global transcription_text
    global total_audio
    
    if not os.path.exists(transcription_text) or not transcription_text:
        try: 
            if not total_audio:
                return jsonify({"error": "No audio segments provided"}), 400
            transcription_text = transcripter.create_transcription(total_audio)
        except Exception as e:
            return jsonify({"error": str(e)}), 500    
    
    analyzer = TextAnalyzer(transcription_text, harassment_keywords)
    api_key = os.environ.get("DEEPSEEK")
    if api_key is None:
        raise ValueError("DEEPSEEK_API_KEY が設定されていません。")
    
    results = analyzer.analyze(api_key=api_key)

    print(json.dumps(results, ensure_ascii=False, indent=2))

    if "deepseek_analysis" in results and results["deepseek_analysis"]:
        deepseek_data = results["deepseek_analysis"]
        conversation_level = deepseek_data.get("conversationLevel")
        harassment_present = deepseek_data.get("harassmentPresent")
        harassment_type = deepseek_data.get("harassmentType")
        repetition = deepseek_data.get("repetition")
        pleasantConversation = deepseek_data.get("pleasantConversation")
        blameOrHarassment = deepseek_data.get("blameOrHarassment")

        print("\n--- DeepSeek 分析結果 ---")
        print(f"会話レベル: {conversation_level}")
        print(f"ハラスメントの有無: {harassment_present}")
        print(f"ハラスメントの種類: {harassment_type}")
        print(f"繰り返しの程度: {repetition}")
        print(f"会話の心地よさ: {pleasantConversation}")
        print(f"非難またはハラスメントの程度: {blameOrHarassment}")
    
    return jsonify({"results": results}), 200


# クラウドから音声を取得してローカルに保存する関数
def download_from_cloud(filename, local_path):
    try:
        payload = {
            "action": "download",
            "fileName": filename
        }
        
        print(f"クラウドから {filename} をダウンロード中...")
        response = requests.post(GAS_URL, json=payload)
        if response.status_code != 200:
            print(f"ダウンロードエラー: ステータスコード {response.status_code}")
            print(f"レスポンス: {response.text}")
            raise Exception(f"クラウドからのダウンロードに失敗しました: {response.text}")
        
        try:
            res_json = response.json()
        except:
            print("JSONデコードエラー、レスポンス内容:")
            print(response.text[:500])  # 最初の500文字だけ表示
            raise Exception("サーバーからの応答をJSONとして解析できませんでした")
        
        if res_json.get("status") != "success":
            print(f"ダウンロードステータスエラー: {res_json.get('message')}")
            raise Exception(f"クラウドからのダウンロードに失敗しました: {res_json.get('message')}")
        
        # Base64文字列をデコード
        base64_data = res_json.get("base64Data")
        if not base64_data:
            print("Base64データが存在しません")
            raise Exception("応答にBase64データが含まれていません")
            
        try:
            audio_binary = base64.b64decode(base64_data)
        except Exception as e:
            print(f"Base64デコードエラー: {str(e)}")
            raise Exception(f"音声データのデコードに失敗しました: {str(e)}")
        
        # 指定パスに保存
        os.makedirs(os.path.dirname(local_path), exist_ok=True)
        with open(local_path, 'wb') as f:
            f.write(audio_binary)
            
        print(f"{filename} をローカルに保存しました: {local_path}")
        
        # データの整合性チェック(ファイルサイズが0より大きいかなど)
        if os.path.getsize(local_path) <= 0:
            raise Exception(f"保存されたファイル {local_path} のサイズが0バイトです")
            
        return local_path
    except Exception as e:
        print(f"ダウンロード中にエラーが発生しました: {str(e)}")
        # エラーを上位に伝播させる
        raise

# クラウドからファイルを削除する関数
def delete_from_cloud(filename):
    payload = {
        "action": "delete",
        "fileName": filename
    }
    response = requests.post(GAS_URL, json=payload)
    if response.status_code != 200:
        raise Exception(f"クラウドからの削除に失敗しました: {response.text}")
    
    res_json = response.json()
    if res_json.get("status") != "success":
        raise Exception(f"クラウドからの削除に失敗しました: {res_json.get('message')}")
    
    return True
# すべてのベース音声ユーザーリストを更新する関数
def update_all_users():
    global all_users
    
    payload = {"action": "list"}
    response = requests.post(GAS_URL, json=payload)
    if response.status_code != 200:
        raise Exception(f"GAS一覧取得エラー: {response.text}")
    
    res_json = response.json()
    if res_json.get("status") != "success":
        raise Exception(f"GAS一覧取得失敗: {res_json.get('message')}")
    
    # ファイル名から拡張子を除去してユーザーリストを作成
    all_users = [os.path.splitext(filename)[0] for filename in res_json.get("fileNames", [])]
    return all_users

# 音声アップロード&解析エンドポイント
@app.route('/upload_audio', methods=['POST'])
def upload_audio():
    global total_audio
    global users
    
    try:
        data = request.get_json()
        if not data or 'audio_data' not in data:
            return jsonify({"error": "音声データがありません"}), 400
            
        # リクエストからユーザーリストを取得(指定がなければ現在のusersを使用)
        if 'selected_users' in data and data['selected_users']:
            users = data['selected_users']
            print(f"選択されたユーザー: {users}")

        if not users:
            return jsonify({"error": "選択されたユーザーがいません"}), 400

        # Base64デコードして音声バイナリを取得
        audio_binary = base64.b64decode(data['audio_data'])
        
        upload_name = 'tmp'
        audio_dir = "/tmp/data"
        os.makedirs(audio_dir, exist_ok=True)
        audio_path = os.path.join(audio_dir, f"{upload_name}.wav")
        with open(audio_path, 'wb') as f:
            f.write(audio_binary)
        
        print(f"処理を行うユーザー: {users}")
        
        # ベース音声を一時ディレクトリにダウンロード
        temp_dir = "/tmp/data/base_audio"
        os.makedirs(temp_dir, exist_ok=True)
        
        # 各ユーザーの参照音声ファイルのパスをリストに格納
        reference_paths = []
        for user in users:
            try:
                ref_path = os.path.join(temp_dir, f"{user}.wav")
                if not os.path.exists(ref_path):
                    # クラウドから取得
                    download_from_cloud(f"{user}.wav", ref_path)
                    print(f"クラウドから {user}.wav をダウンロードしました")
                
                if not os.path.exists(ref_path):
                    return jsonify({"error": "参照音声ファイルが見つかりません", "details": ref_path}), 500
                    
                reference_paths.append(ref_path)
            except Exception as e:
                return jsonify({"error": f"ユーザー {user} の音声取得に失敗しました", "details": str(e)}), 500
        
        # 複数人の場合は参照パスのリストを、1人の場合は単一のパスを渡す
        if len(users) > 1:
            print("複数人の場合の処理")
            matched_times, merged_segments = process.process_multi_audio(reference_paths, audio_path, users, threshold=0.05)
            total_audio = transcripter.save_marged_segments(merged_segments)
            # 各メンバーのrateを計算
            total_time = sum(matched_times)
            rates = [(time / total_time) * 100 if total_time > 0 else 0 for time in matched_times]
            
            # ユーザー名と話した割合をマッピング
            user_rates = {users[i]: rates[i] for i in range(len(users))}
            return jsonify({"rates": rates, "user_rates": user_rates}), 200
        else:
            matched_time, unmatched_time, merged_segments = process.process_audio(reference_paths[0], audio_path, users[0], threshold=0.05)
            total_audio = transcripter.save_marged_segments(merged_segments)
            print("単一ユーザーの処理")
            total_time = matched_time + unmatched_time
            rate = (matched_time / total_time) * 100 if total_time > 0 else 0
            return jsonify({"rate": rate, "user": users[0]}), 200
            
    except Exception as e:
        print("Error in /upload_audio:", str(e))
        return jsonify({"error": "サーバーエラー", "details": str(e)}), 500

# ユーザー選択画面(テンプレート: userSelect.html)
@app.route('/')
@app.route('/userselect', methods=['GET'])
def userselect():
    return render_template('userSelect.html')

# 選択したユーザーを設定するエンドポイント
@app.route('/select_users', methods=['POST'])
def select_users():
    global users
    
    try:
        data = request.get_json()
        if not data or 'users' not in data:
            return jsonify({"error": "ユーザーリストがありません"}), 400
            
        users = data['users']
        print(f"選択されたユーザー: {users}")
        
        return jsonify({"status": "success", "selected_users": users}), 200
    except Exception as e:
        print("Error in /select_users:", str(e))
        return jsonify({"error": "サーバーエラー", "details": str(e)}), 500

@app.route('/reset', methods=['GET'])
def reset():
    global users
    users = []
    global total_audio
    global transcription_text
    
    # 一時ディレクトリのクリーンアップ
    if total_audio:
        process.delete_files_in_directory(total_audio)
        process.delete_files_in_directory('/tmp/data/transcription_audio')
    
    # 書き起こしテキストの削除
    if os.path.exists(transcription_text):
        try:
            os.remove(transcription_text)
            print(f"{transcription_text} を削除しました。")
        except Exception as e:
            print(f"ファイル削除中にエラーが発生しました: {e}")
    
    transcription_text = ""

    return jsonify({"status": "success", "message": "Users reset"}), 200

@app.route('/copy_selected_files', methods=['POST'])
def copy_selected_files():
    try:
        data = request.get_json()
        if not data or "names" not in data:
            return jsonify({"error": "namesパラメータが存在しません"}), 400

        names = data["names"]
        dest_dir = "/tmp/data/selected_audio"  # コピー先のフォルダ
        os.makedirs(dest_dir, exist_ok=True)

        copied_files = []
        for name in names:
            dest_path = os.path.join(dest_dir, f"{name}.wav")
            try:
                # クラウドから直接ダウンロード
                download_from_cloud(f"{name}.wav", dest_path)
                copied_files.append(name)
                print(f"{name}.wav を {dest_path} にダウンロードしました。")
            except Exception as e:
                print(f"ダウンロード中にエラーが発生しました: {e}")
                continue

        return jsonify({"status": "success", "copied": copied_files}), 200

    except Exception as e:
        print("Error in /copy_selected_files:", str(e))
        return jsonify({"error": "サーバー内部エラー", "details": str(e)}), 500

@app.route('/clear_tmp', methods=['GET'])
def clear_tmp():
    try:
        tmp_dir = "/tmp/data"  # アプリケーションが使用しているtmpフォルダ
        # ファイルのみの削除
        process.delete_files_in_directory(tmp_dir)
        # フォルダがあれば再帰的に削除
        for item in os.listdir(tmp_dir):
            item_path = os.path.join(tmp_dir, item)
            if os.path.isdir(item_path):
                shutil.rmtree(item_path)
                print(f"ディレクトリを削除しました: {item_path}")

        return jsonify({"status": "success", "message": "tmp配下がすべて削除されました"}), 200

    except Exception as e:
        print("Error in /clear_tmp:", str(e))
        return jsonify({"error": "サーバー内部エラー", "details": str(e)}), 500

@app.route('/upload_base_audio', methods=['POST'])
def upload_base_audio():
    global all_users
    
    try:
        data = request.get_json()
        if not data or 'audio_data' not in data or 'name' not in data:
            return jsonify({"error": "音声データまたは名前がありません"}), 400
        name = data['name']
        print(f"登録名: {name}")
        
        # GASのアップロードエンドポイントにリクエスト
        payload = {
            "action": "upload",
            "fileName": f"{name}.wav",
            "base64Data": data['audio_data']
        }
        
        response = requests.post(GAS_URL, json=payload)
        if response.status_code != 200:
            return jsonify({"error": "GASアップロードエラー", "details": response.text}), 500
        
        res_json = response.json()
        if res_json.get("status") != "success":
            return jsonify({"error": "GASアップロード失敗", "details": res_json.get("message")}), 500
        
        # 全ユーザーリストを更新
        update_all_users()
        
        return jsonify({"state": "Registration Success!", "driveFileId": res_json.get("fileId")}), 200
    except Exception as e:
        print("Error in /upload_base_audio:", str(e))
        return jsonify({"error": "サーバーエラー", "details": str(e)}), 500

@app.route('/list_base_audio', methods=['GET'])
def list_base_audio():
    try:
        global all_users
        all_users = update_all_users()
        return jsonify({"status": "success", "fileNames": all_users}), 200
    except Exception as e:
        print("Error in /list_base_audio:", str(e))
        return jsonify({"error": "サーバーエラー", "details": str(e)}), 500

if __name__ == '__main__':
    port = int(os.environ.get("PORT", 7860))
    app.run(debug=True, host="0.0.0.0", port=port)