import logging
import json
from django.views.decorators.csrf import csrf_exempt
from vin import VIN
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.shortcuts import render, get_object_or_404, redirect
from django.utils.translation import gettext_lazy as _
from django.db.models import Q
from django.views.generic import (
    View,
    ListView,
    DetailView,
    CreateView,
    UpdateView,
    DeleteView,
    TemplateView
)
from django.utils import timezone, translation
from django.conf import settings
from urllib.parse import urlparse, urlunparse
from django.forms import ChoiceField, ModelForm, RadioSelect
from django.urls import reverse, reverse_lazy
from django.contrib import messages
from django.db.models import Sum, F, Count
from .services import elm, decodevin,get_make,get_model,normalize_name
from . import models, forms
from django_tables2.export.views import ExportMixin


logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


def switch_language(request):
    language = request.GET.get('language', 'en')
    referer = request.META.get('HTTP_REFERER', '/')
    parsed_url = urlparse(referer)
    path_parts = parsed_url.path.split('/')

    if path_parts[1] in dict(settings.LANGUAGES):
        path_parts.pop(1)

    new_path = '/'.join(path_parts)
    new_url = urlunparse(
        (parsed_url.scheme, parsed_url.netloc, new_path, parsed_url.params, parsed_url.query, parsed_url.fragment)
    )

    if language in dict(settings.LANGUAGES):
        logger.debug(f"Switching language to: {language}")
        response = redirect(new_url)
        response.set_cookie(settings.LANGUAGE_COOKIE_NAME, language)
        translation.activate(language)
        request.session[settings.LANGUAGE_COOKIE_NAME] = language
        logger.debug(f"Language switched to: {language}, Session: {request.session[settings.LANGUAGE_COOKIE_NAME]}")
        return response
    else:
        logger.warning(f"Invalid language code: {language}")
        return redirect('/')


class HomeView(LoginRequiredMixin, TemplateView):
    template_name = 'index.html'

    def dispatch(self, request, *args, **kwargs):
        if not hasattr(request.user, 'dealer') or not request.user.is_authenticated:
            messages.error(request, _('You are not associated with any dealer.'))
            return redirect('welcome')
        return super().dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        total_cars = models.Car.objects.count()
        total_reservations = models.CarReservation.objects.filter(reserved_until__gte=timezone.now()).count()
        stats = models.CarFinance.objects.aggregate(
            total_cost_price=Sum('cost_price'),
            total_selling_price=Sum('selling_price'),
        )
        total_cost_price = stats['total_cost_price'] or 0
        total_selling_price = stats['total_selling_price'] or 0
        total_profit = total_selling_price - total_cost_price

        context['total_cars'] = total_cars
        context['total_reservations'] = total_reservations
        context['total_cost_price'] = total_cost_price
        context['total_selling_price'] = total_selling_price
        context['total_profit'] = total_profit
        return context


class WelcomeView(TemplateView):
    template_name = "welcome.html"


class CarCreateView(LoginRequiredMixin, CreateView):
    model = models.Car
    form_class = forms.CarForm
    template_name = 'inventory/car_form.html'
    # success_url = reverse_lazy('inventory_stats')

    def get_success_url(self):
        """Determine the redirect URL based on user choice."""
        if self.request.POST.get('add_another'):
            return reverse('car_add')
        return reverse('inventory_stats')

    def form_valid(self, form):
        form.instance.dealer = self.request.user.dealer
        form.save()
        messages.success(self.request, 'Car saved successfully.')
        return super().form_valid(form)


class AjaxHandlerView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        action = request.GET.get('action')
        handlers = {
            'decode_vin': self.decode_vin,
            'get_models': self.get_models,
            'get_series': self.get_series,
            'get_trims': self.get_trims,
            'get_specifications': self.get_specifications,
        }
        handler = handlers.get(action)
        if handler:
            return handler(request)
        else:
            return JsonResponse({'error': 'Invalid action'}, status=400)

    def decode_vin(self, request):
        vin_no = request.GET.get('vin_no')
        if not vin_no or len(vin_no.strip()) != 17:
            return JsonResponse({'success': False, 'error': 'Invalid VIN number provided.'}, status=400)
        
        vin_no = vin_no.strip()
        vin_data = {}
        decoding_method = ''

        manufacturer_name = model_name = year_model = None
        if not (result :=decodevin(vin_no)):
            return JsonResponse({'success': False, 'error': 'VIN not found in all sources.'}, status=404)        
        
        manufacturer_name,model_name,year_model = result.values()
        make = get_make(manufacturer_name)
        model = get_model(model_name,make)        
        
        logger.info(
            f"VIN decoded using {decoding_method}: Make={manufacturer_name}, Model={model_name}, Year={year_model}"
        )        
        car_model = model
        car_make = make
        
        if not car_make:
            return JsonResponse({'success': False, 'error': 'Manufacturer not found in the database.'}, status=404)
        vin_data['make_id'] = car_make.id_car_make
        vin_data['name'] = car_make.name
        vin_data['arabic_name'] = car_make.arabic_name
         
        if not car_model:
            vin_data['model_id'] = ""            
        else:
            vin_data['model_id'] = car_model.id_car_model
        vin_data['year'] = year_model
        return JsonResponse({'success': True, 'data': vin_data})

    def get_models(self, request):
        make_id = request.GET.get('make_id')
        car_models = models.CarModel.objects.filter(id_car_make=make_id).values('id_car_model', 'name', 'arabic_name')
        return JsonResponse(list(car_models), safe=False)

    def get_series(self, request):
        model_id = request.GET.get('model_id')
        series = models.CarSerie.objects.filter(
            id_car_model=model_id,
        ).values('id_car_serie', 'name', 'arabic_name')
        return JsonResponse(list(series), safe=False)

    def get_trims(self, request):
        serie_id = request.GET.get('serie_id')
        trims = models.CarTrim.objects.filter(
            id_car_serie=serie_id
        ).values('id_car_trim', 'name', 'arabic_name')
        return JsonResponse(list(trims), safe=False)

    def get_specifications(self, request):
        trim_id = request.GET.get('trim_id')
        car_spec_values = models.CarSpecificationValue.objects.filter(id_car_trim=trim_id)
        lang = translation.get_language()
        specs_by_parent = {}
        for value in car_spec_values:
            specification = value.id_car_specification
            parent = specification.id_parent
            parent_id = parent.id_car_specification if parent else 0
            if lang == 'ar':
                parent_name = parent.arabic_name if parent else "Root"
            else:
                parent_name = parent.name if parent else "Root"
            if parent_id not in specs_by_parent:
                specs_by_parent[parent_id] = {'parent_name': parent_name, 'specifications': []}
            spec_data = {
                'specification_id': specification.id_car_specification,
                's_name': specification.arabic_name if lang == 'ar' else specification.name,
                's_value': value.value,
                's_unit': value.unit if value.unit else "",
                'trim_name': value.id_car_trim.name
            }
            specs_by_parent[parent_id]['specifications'].append(spec_data)
        serialized_specs = [
            {'parent_name': v['parent_name'], 'specifications': v['specifications']}
            for v in specs_by_parent.values()
        ]
        return JsonResponse(serialized_specs, safe=False)


class CarInventory(LoginRequiredMixin, ListView):
    model = models.Car
    home_label = _('inventory')
    template_name = 'inventory/car_inventory.html'
    context_object_name = 'cars'
    paginate_by = 10
    ordering = ['receiving_date']

    def get_queryset(self, *args, **kwargs):
        query = self.request.GET.get('q')
        make_id = self.kwargs['make_id']
        model_id = self.kwargs['model_id']
        trim_id = self.kwargs['trim_id']
        cars = models.Car.objects.filter(
            dealer__user=self.request.user,
            id_car_make=make_id,
            id_car_model=model_id,
            id_car_trim=trim_id,).order_by('receiving_date')

        if query:
            cars = cars.filter(Q(vin__icontains=query))
        return cars

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['query'] = self.request.GET.get('q', '')
        context['make_id'] = self.kwargs['make_id']
        context['model_id'] = self.kwargs['model_id']
        context['trim_id'] = self.kwargs['trim_id']
        return context


class CarColorCreate(LoginRequiredMixin, CreateView):
    model = models.CarColors
    form_class = forms.CarColorsForm
    template_name = "inventory/add_colors.html"

    def form_valid(self, form):
        car = get_object_or_404(models.Car, pk=self.kwargs['car_pk'])
        form.instance.car = car
        return super().form_valid(form)

    def get_success_url(self):
        return reverse_lazy('car_detail', kwargs={'pk': self.kwargs['car_pk']})

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['car'] = get_object_or_404(models.Car, pk=self.kwargs['car_pk'])
        return context


@login_required
def inventory_stats_view(request):
    dealer = request.user.dealer

    # Annotate total cars by make, model, and trim
    cars = (
        models.Car.objects.filter(dealer=dealer)
        .select_related('id_car_make', 'id_car_model', 'id_car_trim')
        .annotate(
            make_total=Count('id_car_make'),
            model_total=Count('id_car_model'),
            trim_total=Count('id_car_trim')
        )
    )

    # Prepare the nested structure
    inventory = {}
    for car in cars:
        # Make Level
        make = car.id_car_make
        if make.id_car_make not in inventory:
            inventory[make.id_car_make] = {
                'make_id': make.id_car_make,
                'make_name': make.get_local_name(),
                'total_cars': 0,
                'models': {}
            }
        inventory[make.id_car_make]['total_cars'] += 1

        # Model Level
        model = car.id_car_model
        if model and model.id_car_model not in inventory[make.id_car_make]['models']:
            inventory[make.id_car_make]['models'][model.id_car_model] = {
                'model_id': model.id_car_model,
                'model_name': model.get_local_name(),
                'total_cars': 0,
                'trims': {}
            }
        inventory[make.id_car_make]['models'][model.id_car_model]['total_cars'] += 1

        # Trim Level
        trim = car.id_car_trim
        if trim and trim.id_car_trim not in inventory[make.id_car_make]['models'][model.id_car_model]['trims']:
            inventory[make.id_car_make]['models'][model.id_car_model]['trims'][trim.id_car_trim] = {
                'trim_id': trim.id_car_trim,
                'trim_name': trim.name,
                'total_cars': 0
            }
        inventory[make.id_car_make]['models'][model.id_car_model]['trims'][trim.id_car_trim]['total_cars'] += 1

    # Convert to a list for easier template rendering
    result = {
        'total_cars': cars.count(),
        'makes': [
            {
                'make_id': make_data['make_id'],
                'make_name': make_data['make_name'],
                'total_cars': make_data['total_cars'],
                'models': [
                    {
                        'model_id': model_data['model_id'],
                        'model_name': model_data['model_name'],
                        'total_cars': model_data['total_cars'],
                        'trims': list(model_data['trims'].values())
                    }
                    for model_data in make_data['models'].values()
                ]
            }
            for make_data in inventory.values()
        ]
    }

    return render(request, 'inventory/inventory_stats.html', {'inventory': result})


class CarDetailView(LoginRequiredMixin, DetailView):
    model = models.Car
    template_name = 'inventory/car_detail.html'
    context_object_name = 'car'


class CarFinanceCreateView(LoginRequiredMixin, CreateView):
    model = models.CarFinance
    form_class = forms.CarFinanceForm
    template_name = 'inventory/car_finance_form.html'

    def dispatch(self, request, *args, **kwargs):
        self.car = get_object_or_404(models.Car, pk=self.kwargs['car_pk'])
        return super().dispatch(request, *args, **kwargs)

    def form_valid(self, form):
        form.instance.car = self.car
        messages.success(self.request, _('Car finance details saved successfully.'))
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('car_detail', kwargs={'pk': self.car.pk})

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['car'] = self.car
        return context


class CarFinanceUpdateView(LoginRequiredMixin, UpdateView):
    model = models.CarFinance
    form_class = forms.CarFinanceForm
    template_name = 'inventory/car_finance_form.html'

    def form_valid(self, form):
        messages.success(self.request, _('Car finance updated successfully.'))
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('car_detail', kwargs={'pk': self.object.car.pk})


class CarUpdateView(LoginRequiredMixin, UpdateView):
    model = models.Car
    form_class = forms.CarUpdateForm
    template_name = 'inventory/car_edit.html'

    def form_valid(self, form):
        messages.success(self.request, _('Car updated successfully.'))
        return super().form_valid(form)

    def get_success_url(self):
        return reverse('car_detail', kwargs={'pk': self.object.pk})


class CarDeleteView(LoginRequiredMixin, DeleteView):
    model = models.Car
    template_name = 'inventory/car_confirm_delete.html'
    success_url = reverse_lazy('inventory_stats')

    def delete(self, request, *args, **kwargs):
        messages.success(request, _('Car deleted successfully.'))
        return super().delete(request, *args, **kwargs)


class CustomCardCreateView(LoginRequiredMixin, CreateView):
    model = models.CustomCard
    form_class = forms.CustomCardForm
    template_name = "inventory/add_custom_card.html"

    def form_valid(self, form):
        car = get_object_or_404(models.Car, pk=self.kwargs['car_pk'])
        form.instance.car = car
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['car'] = get_object_or_404(models.Car, pk=self.kwargs['car_pk'])
        return context

    def get_success_url(self):
        messages.success(self.request, _("Custom Card added successfully."))
        return reverse_lazy('car_detail', kwargs={'pk': self.kwargs['car_pk']})


@login_required()
def reserve_car_view(request, car_id):
    if request.method == "POST":
        car = get_object_or_404(models.Car, pk=car_id)
        if car.is_reserved():
            messages.error(request, _("This car is already reserved."))
            return redirect('car_detail', pk=car.pk)

        try:
            reserved_until = timezone.now() + timezone.timedelta(hours=24)
            models.CarReservation.objects.create(
                car=car,
                reserved_by=request.user,
                reserved_until=reserved_until
            )
            messages.success(request, _("Car reserved successfully."))
        except Exception as e:
            messages.error(request, f"Error reserving car: {e}")

        return redirect('car_detail', pk=car.pk)
    return JsonResponse({"success": False, "message": "Invalid request method."}, status=400)


@login_required
def manage_reservation(request, reservation_id):
    reservation = get_object_or_404(models.CarReservation, pk=reservation_id, reserved_by=request.user)

    if request.method == "POST":
        action = request.POST.get("action")
        if action == "renew":
            reservation.reserved_until = timezone.now() + timezone.timedelta(hours=24)
            reservation.save()
            messages.success(request, _("Reservation renewed successfully."))
            return redirect('car_detail', pk=reservation.car.pk)

        elif action == "cancel":
            reservation.delete()
            messages.success(request, _("Reservation canceled successfully."))
            return redirect('car_detail', pk=reservation.car.pk)

        else:
            return JsonResponse({"success": False, "message": _("Invalid action.")}, status=400)

    return JsonResponse({"success": False, "message": _("Invalid request method.")}, status=400)


class DealerListView(LoginRequiredMixin, ListView):
    model = models.Dealer
    template_name = 'dealer_list.html'
    context_object_name = 'dealers'


class DealerDetailView(LoginRequiredMixin, DetailView):
    model = models.Dealer
    template_name = 'dealers/dealer_detail.html'
    context_object_name = 'dealer'


class DealerCreateView(LoginRequiredMixin, CreateView):
    model = models.Dealer
    form_class = forms.DealerForm
    template_name = 'dealer_form.html'
    success_url = reverse_lazy('dealer_list')

    def form_valid(self, form):
        messages.success(self.request, _('Dealer created successfully.'))
        return super().form_valid(form)


class DealerUpdateView(LoginRequiredMixin, UpdateView):
    model = models.Dealer
    form_class = forms.DealerForm
    template_name = 'dealers/dealer_form.html'
    success_url = reverse_lazy('dealer_detail')

    def form_valid(self, form):
        messages.success(self.request, _('Dealer updated successfully.'))
        return super().form_valid(form)


class DealerDeleteView(LoginRequiredMixin, DeleteView):
    model = models.Dealer
    template_name = 'dealer_confirm_delete.html'
    success_url = reverse_lazy('dealer_list')

    def delete(self, request, *args, **kwargs):
        messages.success(request, _('Dealer deleted successfully.'))
        return super().delete(request, *args, **kwargs)


class CustomerListView(LoginRequiredMixin, ListView):
    model = models.Customer
    home_label = _('customers')
    context_object_name = 'customers'
    paginate_by = 10
    template_name = "customers/customer_list.html"

    def get_queryset(self):
        query = self.request.GET.get('q')
        customers = models.Customer.objects.filter(dealer__user=self.request.user)

        if query:
            customers = customers.filter(
                Q(national_id__icontains=query) |
                Q(first_name__icontains=query) |
                Q(last_name__icontains=query)
            )
        return customers

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['query'] = self.request.GET.get('q', '')
        return context


class CustomerDetailView(LoginRequiredMixin, DetailView):
    model = models.Customer
    template_name = 'customers/view_customer.html'
    context_object_name = 'customer'


class CustomerCreateView(LoginRequiredMixin, CreateView):
    model = models.Customer
    form_class = forms.CustomerForm
    template_name = 'customers/customer_form.html'
    success_url = reverse_lazy('customer_list')

    def form_valid(self, form):
        if form.is_valid():
            form.instance.dealer = self.request.user.dealer
            form.save()
            messages.success(self.request, _('Customer created successfully.'))
            return super().form_valid(form)
        else:
            return form.errors


class CustomerUpdateView(LoginRequiredMixin, UpdateView):
    model = models.Customer
    form_class = forms.CustomerForm
    template_name = 'customers/customer_form.html'
    success_url = reverse_lazy('customer_list')

    def form_valid(self, form):
        if form.is_valid():
            form.instance.dealer = self.request.user.dealer
            form.save()
            messages.success(self.request, _('Customer updated successfully.'))
            return super().form_valid(form)
        else:
            return form.errors


@login_required
def delete_customer(request, pk):
    customer = get_object_or_404(models.Customer, pk=pk)
    customer.delete()
    messages.success(request, _('Customer deleted successfully.'))
    return redirect('customer_list')


class VendorListView(LoginRequiredMixin, ListView):
    model = models.Vendor
    context_object_name = 'vendors'
    paginate_by = 10
    template_name = "vendors/vendors_list.html"


class VendorDetailView(LoginRequiredMixin, DetailView):
    model = models.Vendor
    template_name = "vendors/view_vendor.html"


class VendorCreateView(LoginRequiredMixin, CreateView):
    model = models.Vendor
    form_class = forms.VendorForm
    template_name = 'vendors/vendor_form.html'
    success_url = reverse_lazy('vendor_list')

    def form_valid(self, form):
        if form.is_valid():
            form.instance.dealer = self.request.user.dealer
            form.save()
            messages.success(self.request, _('Vendor created successfully.'))
            return super().form_valid(form)
        else:
            return form.errors


class VendorUpdateView(LoginRequiredMixin, UpdateView):
    model = models.Vendor
    form_class = forms.VendorForm
    template_name = 'vendors/vendor_form.html'
    success_url = reverse_lazy('vendor_list')

    def form_valid(self, form):
        if form.is_valid():
            form.instance.dealer = self.request.user.dealer
            form.save()
            messages.success(self.request, _('Vendor updated successfully.'))
            return super().form_valid(form)
        else:
            return form.errors


@login_required
def delete_vendor(request, pk):
    vendor = get_object_or_404(models.Vendor, pk=pk)
    vendor.delete()
    messages.success(request, _('Vendor deleted successfully.'))
    return redirect('vendor_list')


class QuotationCreateView(LoginRequiredMixin, CreateView):
    model = models.SaleQuotation
    form_class = forms.QuotationForm
    template_name = 'sales/quotation_form.html'

    def form_valid(self, form):
        quotation = form.save()
        selected_cars = form.cleaned_data.get("cars")
        for car in selected_cars:
            car_finance = car.finances.first()
            if car_finance:
                models.SaleQuotationCar.objects.create(
                    quotation=quotation,
                    car=car,
                )

        messages.success(self.request, _("Quotation created successfully."))
        return redirect('quotation_list')


class QuotationListView(LoginRequiredMixin, ListView):
    model = models.SaleQuotation
    template_name = "sales/quotation_list.html"
    context_object_name = "quotations"
    paginate_by = 10

    def get_queryset(self):
        status = self.request.GET.get("status")
        queryset = models.SaleQuotation.objects.all()
        if status:
            queryset = queryset.filter(status=status)
        return queryset


class QuotationDetailView(LoginRequiredMixin, DetailView):
    model = models.SaleQuotation
    template_name = "sales/quotation_detail.html"
    context_object_name = "quotation"


@login_required
def confirm_quotation(request, pk):
    quotation = get_object_or_404(models.SaleQuotation, pk=pk)
    try:
        quotation.confirm()
        models.SalesOrder.objects.create(
            quotation=quotation,
            total_amount=quotation.quotation_cars.aggregate(Sum("total_amount"))["total_amount__sum"],
        )
        messages.success(request, _("Quotation confirmed and sales order created."))
    except ValueError as e:
        messages.error(request, str(e))
    return redirect("quotation_detail", pk=pk)


class SalesOrderDetailView(LoginRequiredMixin, DetailView):
    model = models.SalesOrder
    template_name = "sales/sales_order_detail.html"
    context_object_name = "sales_order"