import json
import logging
import traceback

from flask import Blueprint, jsonify, make_response

from ..models.database import get_db_connection, get_logs_for_research

# Initialize logger
logger = logging.getLogger(__name__)

# Create a Blueprint for the history routes
history_bp = Blueprint("history", __name__)


@history_bp.route("/history", methods=["GET"])
def get_history():
    """Get the research history"""
    try:
        conn = get_db_connection()
        conn.row_factory = lambda cursor, row: {
            column[0]: row[idx] for idx, column in enumerate(cursor.description)
        }
        cursor = conn.cursor()

        # Get all history records ordered by latest first
        cursor.execute("SELECT * FROM research_history ORDER BY created_at DESC")
        results = cursor.fetchall()
        conn.close()

        # Convert to list of dicts
        history = []
        for result in results:
            item = dict(result)

            # Ensure all keys exist with default values
            if "id" not in item:
                item["id"] = None
            if "query" not in item:
                item["query"] = "Untitled Research"
            if "mode" not in item:
                item["mode"] = "quick"
            if "status" not in item:
                item["status"] = "unknown"
            if "created_at" not in item:
                item["created_at"] = None
            if "completed_at" not in item:
                item["completed_at"] = None
            if "duration_seconds" not in item:
                item["duration_seconds"] = None
            if "report_path" not in item:
                item["report_path"] = None
            if "metadata" not in item:
                item["metadata"] = "{}"
            if "progress_log" not in item:
                item["progress_log"] = "[]"

            # Ensure timestamps are in ISO format
            if item["created_at"] and "T" not in item["created_at"]:
                try:
                    # Convert to ISO format if it's not already
                    from dateutil import parser

                    dt = parser.parse(item["created_at"])
                    item["created_at"] = dt.isoformat()
                except Exception:
                    pass

            if item["completed_at"] and "T" not in item["completed_at"]:
                try:
                    # Convert to ISO format if it's not already
                    from dateutil import parser

                    dt = parser.parse(item["completed_at"])
                    item["completed_at"] = dt.isoformat()
                except Exception:
                    pass

            # Recalculate duration based on timestamps if it's null but both timestamps exist
            if (
                item["duration_seconds"] is None
                and item["created_at"]
                and item["completed_at"]
            ):
                try:
                    from dateutil import parser

                    start_time = parser.parse(item["created_at"])
                    end_time = parser.parse(item["completed_at"])
                    item["duration_seconds"] = int(
                        (end_time - start_time).total_seconds()
                    )
                except Exception as e:
                    print(f"Error recalculating duration: {str(e)}")

            history.append(item)

        # Format response to match what client expects
        response_data = {
            "status": "success",
            "items": history,  # Use 'items' key as expected by client
        }

        # Add CORS headers
        response = make_response(jsonify(response_data))
        response.headers.add("Access-Control-Allow-Origin", "*")
        response.headers.add(
            "Access-Control-Allow-Headers", "Content-Type,Authorization"
        )
        response.headers.add(
            "Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS"
        )
        return response
    except Exception as e:
        print(f"Error getting history: {str(e)}")
        print(traceback.format_exc())
        # Return empty array with CORS headers
        response = make_response(
            jsonify({"status": "error", "items": [], "message": str(e)})
        )
        response.headers.add("Access-Control-Allow-Origin", "*")
        response.headers.add(
            "Access-Control-Allow-Headers", "Content-Type,Authorization"
        )
        response.headers.add(
            "Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS"
        )
        return response


@history_bp.route("/status/<int:research_id>")
def get_research_status(research_id):
    conn = get_db_connection()
    conn.row_factory = lambda cursor, row: {
        column[0]: row[idx] for idx, column in enumerate(cursor.description)
    }
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM research_history WHERE id = ?", (research_id,))
    result = cursor.fetchone()
    conn.close()

    if not result:
        return jsonify({"status": "error", "message": "Research not found"}), 404

    # Import globals from research routes
    from .research_routes import get_globals

    globals_dict = get_globals()
    active_research = globals_dict["active_research"]

    # Add progress information
    if research_id in active_research:
        result["progress"] = active_research[research_id]["progress"]
        result["log"] = active_research[research_id]["log"]
    elif result.get("status") == "completed":
        result["progress"] = 100
        try:
            result["log"] = json.loads(result.get("progress_log", "[]"))
        except Exception:
            result["log"] = []
    else:
        result["progress"] = 0
        try:
            result["log"] = json.loads(result.get("progress_log", "[]"))
        except Exception:
            result["log"] = []

    return jsonify(result)


@history_bp.route("/details/<int:research_id>")
def get_research_details(research_id):
    """Get detailed progress log for a specific research"""
    conn = get_db_connection()
    conn.row_factory = lambda cursor, row: {
        column[0]: row[idx] for idx, column in enumerate(cursor.description)
    }
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM research_history WHERE id = ?", (research_id,))
    result = cursor.fetchone()
    conn.close()

    if not result:
        return jsonify({"status": "error", "message": "Research not found"}), 404

    # Get logs from the dedicated log database
    logs = get_logs_for_research(research_id)

    # Import globals from research routes
    from .research_routes import get_globals

    globals_dict = get_globals()
    active_research = globals_dict["active_research"]

    # If this is an active research, merge with any in-memory logs
    if research_id in active_research:
        # Use the logs from memory temporarily until they're saved to the database
        memory_logs = active_research[research_id]["log"]

        # Filter out logs that are already in the database by timestamp
        db_timestamps = {log["time"] for log in logs}
        unique_memory_logs = [
            log for log in memory_logs if log["time"] not in db_timestamps
        ]

        # Add unique memory logs to our return list
        logs.extend(unique_memory_logs)

        # Sort logs by timestamp
        logs.sort(key=lambda x: x["time"])

    return jsonify(
        {
            "research_id": research_id,
            "query": result.get("query"),
            "mode": result.get("mode"),
            "status": result.get("status"),
            "progress": active_research.get(research_id, {}).get(
                "progress", 100 if result.get("status") == "completed" else 0
            ),
            "created_at": result.get("created_at"),
            "completed_at": result.get("completed_at"),
            "log": logs,
        }
    )


@history_bp.route("/report/<int:research_id>")
def get_report(research_id):
    conn = get_db_connection()
    conn.row_factory = lambda cursor, row: {
        column[0]: row[idx] for idx, column in enumerate(cursor.description)
    }
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM research_history WHERE id = ?", (research_id,))
    result = cursor.fetchone()
    conn.close()

    if not result or not result.get("report_path"):
        return jsonify({"status": "error", "message": "Report not found"}), 404

    try:
        with open(result["report_path"], "r", encoding="utf-8") as f:
            content = f.read()

        # Create an enhanced metadata dictionary with database fields
        enhanced_metadata = {
            "query": result.get("query", "Unknown query"),
            "mode": result.get("mode", "quick"),
            "created_at": result.get("created_at"),
            "completed_at": result.get("completed_at"),
            "duration": result.get("duration_seconds"),
        }

        # Also include any stored metadata
        stored_metadata = json.loads(result.get("metadata", "{}"))
        if stored_metadata and isinstance(stored_metadata, dict):
            enhanced_metadata.update(stored_metadata)

        return jsonify(
            {
                "status": "success",
                "content": content,
                "query": result.get("query"),
                "mode": result.get("mode"),
                "created_at": result.get("created_at"),
                "completed_at": result.get("completed_at"),
                "metadata": enhanced_metadata,
            }
        )
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500


@history_bp.route("/markdown/<int:research_id>")
def get_markdown(research_id):
    """Get markdown export for a specific research"""
    conn = get_db_connection()
    conn.row_factory = lambda cursor, row: {
        column[0]: row[idx] for idx, column in enumerate(cursor.description)
    }
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM research_history WHERE id = ?", (research_id,))
    result = cursor.fetchone()
    conn.close()

    if not result or not result.get("report_path"):
        return jsonify({"status": "error", "message": "Report not found"}), 404

    try:
        with open(result["report_path"], "r", encoding="utf-8") as f:
            content = f.read()
        return jsonify({"status": "success", "content": content})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500


@history_bp.route("/logs/<int:research_id>")
def get_research_logs(research_id):
    """Get logs for a specific research ID"""
    # First check if the research exists
    conn = get_db_connection()
    conn.row_factory = lambda cursor, row: {
        column[0]: row[idx] for idx, column in enumerate(cursor.description)
    }
    cursor = conn.cursor()
    cursor.execute("SELECT id FROM research_history WHERE id = ?", (research_id,))
    result = cursor.fetchone()
    conn.close()

    if not result:
        return jsonify({"status": "error", "message": "Research not found"}), 404

    # Retrieve logs from the database
    logs = get_logs_for_research(research_id)

    # Format logs correctly if needed
    formatted_logs = []
    for log in logs:
        # Ensure each log has time, message, and type fields
        log_entry = {
            "time": log.get("time", ""),
            "message": log.get("message", "No message"),
            "type": log.get("type", "info"),
        }
        formatted_logs.append(log_entry)

    # Import globals from research routes
    from .research_routes import get_globals

    globals_dict = get_globals()
    active_research = globals_dict["active_research"]

    # Add any current logs from memory if this is an active research
    if research_id in active_research and active_research[research_id].get("log"):
        # Use the logs from memory temporarily until they're saved to the database
        memory_logs = active_research[research_id]["log"]

        # Format memory logs too
        for log in memory_logs:
            log_entry = {
                "time": log.get("time", ""),
                "message": log.get("message", "No message"),
                "type": log.get("type", "info"),
            }

            # Check if this log is already in our formatted logs by timestamp
            if not any(flog["time"] == log_entry["time"] for flog in formatted_logs):
                formatted_logs.append(log_entry)

        # Sort logs by timestamp
        formatted_logs.sort(key=lambda x: x["time"])

    return jsonify({"status": "success", "logs": formatted_logs})
