from django.shortcuts import render
from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.admin.views.decorators import staff_member_required
from django.http import HttpResponseNotFound, HttpResponseBadRequest, FileResponse, Http404, JsonResponse
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings
from datetime import datetime
import os
import json
import logging

logger = logging.getLogger(__name__)


def parse_log_line(line):
    """
    Log satırını JSON formatından parse eder
    """
    try:
        log_data = json.loads(line)
        level = log_data.get("levelname", "UNKNOWN")
        exc_info = log_data.get("exc_info", "")
        info = exc_info.split("\n") if exc_info else []

        # Tarihi milisaniyeye kadar dönüştürür
        asctime_str = log_data.get("asctime", "")
        asctime = datetime.strptime(asctime_str, "%Y-%m-%d %H:%M:%S,%f")

        return {
            "level": level,
            "name": log_data.get("name", ""),
            "asctime": asctime,
            "timestamp": asctime_str,
            "message": log_data.get("message", ""),
            "status_code": log_data.get("status_code", ""),
            "task_name": log_data.get("taskName", ""),
            "request": log_data.get("request", ""),
            "info": info,
            "raw": line,
        }
    except json.JSONDecodeError as e:
        return {
            "level": "ERROR",
            "timestamp": "",
            "message": "Invalid JSON format",
            "status_code": "",
            "task_name": "",
            "request": "",
            "raw": line,
        }


@login_required
@user_passes_test(lambda u: u.is_staff)
def log_view(request):
    """
    Log dosyalarını görüntülemek için view
    """
    try:
        # Log dizinini al (settings'den veya varsayılan)
        log_dir = getattr(settings, 'LOG_HUB_LOG_DIR', os.path.join(settings.BASE_DIR, 'logs'))
        log_files = [f for f in os.listdir(log_dir) if f.endswith('.log')]  # .log dosyalarını bul
        log_type = request.GET.get('log_type', log_files[0] if log_files else None)  # Seçilen log dosyası
        search_query = request.GET.get('q', '')  # Arama kelimesi
        log_level = request.GET.get('level', '')  # Log seviyesi (INFO, ERROR, WARNING)
        limit = int(request.GET.get('limit', 50))  # Gösterilecek log sayısı (default: 50)
        start_date = request.GET.get('start_date', '')
        end_date = request.GET.get('end_date', '')
        status_code = request.GET.get('status_code', '') # status koduna göre listele
        exclude = request.GET.get('exclude', '') # Listelerken hariç tutulacak log satırları(anahtar kelimeler)

        if log_type and log_type in log_files:
            log_file_path = os.path.join(log_dir, log_type)
        else:
            return HttpResponseNotFound("Seçilen log dosyası bulunamadı.")
        
        try:
            start_datetime = datetime.strptime(start_date, "%Y-%m-%dT%H:%M") if start_date else None
            end_datetime = datetime.strptime(end_date, "%Y-%m-%dT%H:%M") if end_date else None
        except ValueError:
            return HttpResponseBadRequest("Invalid date format. Please use 'YYYY-MM-DDTHH:MM' format.")

        logs = []
        hata = None
        try:
            with open(log_file_path, 'r') as file:
                exclude_keywords = [kelime.strip().lower() for kelime in exclude.split(",")]
                s = 0
                for line in file:
                    log_data = parse_log_line(line)
                    
                    # Filtreleme
                    if exclude and any(kelime in line.lower() for kelime in exclude_keywords):
                        continue
                    if status_code and status_code != log_data["status_code"]:
                        continue
                    if log_level and log_level != log_data["level"]:
                        continue
                    if search_query and search_query.lower() not in log_data["raw"].lower():
                        continue
                    if start_datetime and log_data["asctime"] and log_data["asctime"] < start_datetime:
                        continue
                    if end_datetime and log_data["asctime"] and log_data["asctime"] > end_datetime:
                        continue
                    logs.append(log_data)
                    s += 1
                    if s >= int(limit):
                        break
                logs.reverse() # tersten listele
        except Exception as e:
            hata = f"Log dosyası oluşurken bir hata oluştu: {str(e)}"

        # Template path'ini settings'den al veya varsayılan kullan
        template_name = getattr(settings, 'LOG_HUB_TEMPLATE', 'log_hub/logging.html')

        return render(request, template_name, {
            "hata": hata,
            'log_count': len(logs),
            'logs': logs,
            'log_files': log_files,
            'selected_log_type': log_type,
            'search_query': search_query,
            'log_level': log_level,
            'start_date': start_date,
            'end_date': end_date,
            'limit': limit,
            'status_code': status_code,
            'exclude': exclude,
        })
    except Exception as e:
        return HttpResponseNotFound(f"Belirsiz Parametre, {e}")


@staff_member_required
@require_http_methods(["POST"])
@csrf_exempt
def clear_log(request, log_file_name):
    """
    Log dosyasını temizlemek için view
    """
    log_dir = getattr(settings, 'LOG_HUB_LOG_DIR', os.path.join(settings.BASE_DIR, 'logs'))
    log_file_path = os.path.join(log_dir, log_file_name)

    if not os.path.exists(log_file_path):
        raise Http404("Belirtilen log dosyası bulunamadı.")
    
    try:
        with open(log_file_path, 'w'):
            pass  # Dosya içeriğini temizle

        return JsonResponse({"status": "success", "message": f"'{log_file_name}' başarıyla temizlendi."})
    except Exception as e:
        return JsonResponse({"status": "error", "message": f"Dosya temizlenirken bir hata oluştu: {str(e)}"}, status=500)


@staff_member_required
def download_log(request, log_file_name):
    """
    Log dosyasını indirmek için view
    """
    log_dir = getattr(settings, 'LOG_HUB_LOG_DIR', os.path.join(settings.BASE_DIR, 'logs'))
    log_file_path = os.path.join(log_dir, log_file_name)

    if not os.path.exists(log_file_path):
        raise Http404("Seçilen log dosyası bulunamadı.")

    return FileResponse(open(log_file_path, 'rb'), as_attachment=True, filename=log_file_name) 