from decimal import Decimal

from django.contrib import messages
from django.db.models import Sum
from django.http import HttpResponse, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.utils import timezone
from django.views.decorators.http import require_GET, require_http_methods, require_POST

from .forms import ReportFilterForm, TripFilterForm, TripForm
from .models import Trip
from .utils import apply_trip_filters, calculate_google_maps_distance, export_trips_csv, report_queryset, summarize_trips


DEFAULT_META_DESCRIPTION = "Mobile-friendly mileage logging with odometer history, Google Maps assist, and IRS-style reporting."


def latest_trip_with_odometer():
    return Trip.objects.exclude(end_odometer__isnull=True).order_by("-date", "-end_time", "-created_at").first()


def home(request):
    today = timezone.localdate()
    current_month = Trip.objects.filter(date__year=today.year, date__month=today.month)
    ytd = Trip.objects.filter(date__year=today.year)
    recent_trips = Trip.objects.all()[:5]

    month_business = current_month.filter(trip_type=Trip.TripType.BUSINESS).aggregate(total=Sum("distance_miles"))["total"] or Decimal("0.0")
    ytd_business = ytd.filter(trip_type=Trip.TripType.BUSINESS).aggregate(total=Sum("distance_miles"))["total"] or Decimal("0.0")
    business_trip_count = current_month.filter(trip_type=Trip.TripType.BUSINESS).count()
    last_trip = Trip.objects.order_by("-date", "-end_time", "-created_at").first()
    latest_odo = latest_trip_with_odometer()

    context = {
        "project_name": "MileLedger",
        "meta_title": "MileLedger | IRS-friendly mileage tracking for mobile",
        "meta_description": DEFAULT_META_DESCRIPTION,
        "month_business": month_business,
        "ytd_business": ytd_business,
        "business_trip_count": business_trip_count,
        "recent_trips": recent_trips,
        "last_trip": last_trip,
        "latest_end_odometer": latest_odo.end_odometer if latest_odo else None,
        "report_month": today.month,
        "report_year": today.year,
        "empty_state": not Trip.objects.exists(),
    }
    return render(request, "core/index.html", context)


@require_http_methods(["GET", "POST"])
def trip_create(request):
    latest_odo = latest_trip_with_odometer()
    latest_end_odometer = latest_odo.end_odometer if latest_odo else None
    if request.method == "POST":
        form = TripForm(request.POST, latest_end_odometer=latest_end_odometer)
        if form.is_valid():
            trip = form.save()
            messages.success(request, "Trip saved. Your mileage log is updated and ready for review.")
            return redirect("trip_detail", pk=trip.pk)
    else:
        now = timezone.localtime(timezone.now())
        form = TripForm(initial={"date": timezone.localdate(), "start_time": now.strftime("%H:%M"), "end_time": now.strftime("%H:%M"), "trip_type": Trip.TripType.BUSINESS}, latest_end_odometer=latest_end_odometer)

    return render(request, "core/trip_form.html", {"form": form, "page_heading": "Add a mileage entry", "submit_label": "Save trip", "meta_title": "Log a trip | MileLedger", "meta_description": DEFAULT_META_DESCRIPTION, "latest_end_odometer": latest_end_odometer, "trip": None})


@require_http_methods(["GET", "POST"])
def trip_update(request, pk):
    trip = get_object_or_404(Trip, pk=pk)
    if request.method == "POST":
        form = TripForm(request.POST, instance=trip)
        if form.is_valid():
            trip = form.save()
            messages.success(request, "Trip updated. Your mileage history now reflects the latest details.")
            return redirect("trip_detail", pk=trip.pk)
    else:
        form = TripForm(instance=trip)

    return render(request, "core/trip_form.html", {"form": form, "page_heading": "Update trip details", "submit_label": "Save changes", "meta_title": "Edit trip | MileLedger", "meta_description": DEFAULT_META_DESCRIPTION, "trip": trip, "latest_end_odometer": None})


@require_GET
def trip_list(request):
    form = TripFilterForm(request.GET or None)
    trips = Trip.objects.all()
    if form.is_valid():
        trips = apply_trip_filters(trips, form.cleaned_data)
    context = {"form": form, "trips": trips[:100], "summary": summarize_trips(trips), "meta_title": "Trip history | MileLedger", "meta_description": "Review, filter, and audit mileage entries."}
    return render(request, "core/trip_list.html", context)


@require_GET
def trip_detail(request, pk):
    trip = get_object_or_404(Trip, pk=pk)
    return render(request, "core/trip_detail.html", {"trip": trip, "meta_title": f"Trip on {trip.date:%b %d, %Y} | MileLedger", "meta_description": "Trip detail and audit-ready timestamps."})


@require_http_methods(["GET", "POST"])
def trip_delete(request, pk):
    trip = get_object_or_404(Trip, pk=pk)
    if request.method == "POST":
        trip.delete()
        messages.success(request, "Trip deleted.")
        return redirect("trip_list")
    return render(request, "core/trip_detail.html", {"trip": trip, "confirm_delete": True, "meta_title": "Delete trip | MileLedger", "meta_description": "Confirm trip deletion."})


@require_GET
def report_view(request):
    today = timezone.localdate()
    initial = {"report_type": "month", "month": today.month, "year": today.year}
    form = ReportFilterForm(request.GET or initial)
    trips = Trip.objects.none()
    summary = {"business_miles": Decimal("0.0"), "non_business_miles": Decimal("0.0"), "total_miles": Decimal("0.0"), "trip_count": 0}
    if form.is_valid():
        trips = report_queryset(form.cleaned_data)
        summary = summarize_trips(trips)
    return render(request, "core/report.html", {"form": form, "trips": trips, "summary": summary, "meta_title": "IRS-style mileage report | MileLedger", "meta_description": "Generate monthly, annual, or custom mileage reports and export them to CSV."})


@require_GET
def report_export_csv(request):
    today = timezone.localdate()
    initial = {"report_type": "month", "month": today.month, "year": today.year}
    form = ReportFilterForm(request.GET or initial)
    if not form.is_valid():
        messages.error(request, "Choose a valid report filter before exporting.")
        return redirect("report_view")

    trips = report_queryset(form.cleaned_data)
    response = HttpResponse(export_trips_csv(trips), content_type="text/csv")
    response["Content-Disposition"] = 'attachment; filename="mileage-report.csv"'
    return response


@require_POST
def distance_estimate(request):
    start_location = (request.POST.get("start_location") or "").strip()
    end_location = (request.POST.get("end_location") or "").strip()
    if not start_location or not end_location:
        return JsonResponse({"ok": False, "message": "Enter both a start and destination first."}, status=400)

    result = calculate_google_maps_distance(start_location, end_location)
    status = 200 if result.ok else 422
    return JsonResponse({"ok": result.ok, "miles": float(result.miles) if result.miles is not None else None, "message": result.message}, status=status)
