import json
import ast
from amadeus import Client, ResponseError, Location
from django.shortcuts import render
from django.contrib import messages
from .flight import Flight
from .booking import Booking
from django.http import HttpResponse
import ast
import django_pesapal
from django_pesapal.views import PaymentRequestMixin
from django.views.generic import TemplateView
from django.conf import settings
from .models import *
# from urllib.parse import urlencode



amadeus = Client(
    client_id='',
    client_secret=''
)


def testing(request):
    # Retrieve data from the UI form
    return render(request, "demo/test.html")


def demo(request):
    if request.method == 'POST':
        # print(request.method)
        # Retrieve data from the UI form
        origin = request.POST.get("Origin")
        destination = request.POST.get("Destination")
        departure_date = request.POST.get("Departuredate")
        return_date = request.POST.get("Returndate")
        # print(origin, destination, departure_date, return_date)

        # Prepare url parameters for search
        kwargs = {
            "originLocationCode": origin,
            "destinationLocationCode": destination,
            "departureDate": departure_date,
            "adults": 1,
        }

        # For a round trip, we use AI Trip Purpose Prediction
        # to predict if it is a leisure or business trip
        tripPurpose = ""
        if return_date:
            # Adds the parameter returnDate for the Flight Offers Search API call
            kwargs["returnDate"] = return_date
            kwargs_trip_purpose = {
                "originLocationCode": origin,
                "destinationLocationCode": destination,
                "departureDate": departure_date,
                "returnDate": return_date,
            }
            try:
                # Calls Trip Purpose Prediction API
                trip_purpose_response = amadeus.travel.predictions.trip_purpose.get(
                    **kwargs_trip_purpose
                ).data
                tripPurpose = trip_purpose_response["result"]
            except ResponseError as error:
                print(error)
                messages.add_message(
                    request, messages.ERROR, error.response.result["errors"][0]["detail"]
                )
                return render(request, "demo/home.html", {})

        # Perform flight search based on previous inputs
        if origin and destination and departure_date:
            # print(origin, destination, departure_date)
            try:
                search_flights = amadeus.shopping.flight_offers_search.get(**kwargs)
                # print(search_flights)
            except ResponseError as error:
                print('Error is', error)
                messages.add_message(
                    request, messages.ERROR, error.response.result["errors"][0]["detail"]
                )
                return render(request, "demo/home.html", {})
            # try:
            #     country = search_flights.result['dictionaries'].get('locations').get(destination).get('countryCode')
            #     # Get the travel restrictions for the destination
            #     travel_restrictions = amadeus.duty_of_care.diseases.covid19_report.get(countryCode=country)
            #     documents = travel_restrictions.data['areaAccessRestriction']['declarationDocuments']['text']
            #     covid_tests = ''
            #     if 'text' in travel_restrictions.data['areaAccessRestriction']['travelTest']:
            #         covid_tests = travel_restrictions.data['areaAccessRestriction']['travelTest']['text']
            #     else:
            #         covid_tests = travel_restrictions.data['areaAccessRestriction']['travelTest']['travelTestConditionsAndRules'][0]['scenarios'][0]['condition']['textualScenario']
            # except (ResponseError, KeyError, AttributeError) as error:
            #     print('The error is', error)
            #     messages.add_message(
            #         request, messages.ERROR, 'No results found'
            #     )
            #     return render(request, "demo/home.html", {})
            search_flights_returned = []
            response = ""
            for flight in search_flights.data:
                offer = Flight(flight).construct_flights()
                search_flights_returned.append(offer)
                response = zip(search_flights_returned, search_flights.data)

            return render(
                request,
                "demo/home.html",
                {
                    "response": response,
                    "origin": origin,
                    "destination": destination,
                    "departureDate": departure_date,
                    "returnDate": return_date,
                    "tripPurpose": tripPurpose,
                    "request_method": request.method
                #     "country": country,
                #     "documents": documents,
                #     "covid_tests": covid_tests
                },
            )
        return render(request, "demo/home.html", {})
    else:
        # print(request.method)
        return render(request, 'demo/home.html')


def book_flight(request, flight):
    new_traveler = request.POST.get("passengerName")
    print('Passenger name is:', new_traveler)
    
    # Use Flight Offers Price to confirm price and availability
    try:
        flight_price_confirmed = amadeus.shopping.flight_offers.pricing.post(
            ast.literal_eval(flight)
        ).data["flightOffers"]
        print("Confirm price successful")
    except (ResponseError, KeyError, AttributeError) as error:
        print("We have an error on confirming price")
        messages.add_message(request, messages.ERROR, error.response.body)
        return render(request, "demo/home.html", {})
    
    # This returns the final confirmed price
    flight_offer = flight_price_confirmed
    print(type(flight_price_confirmed))
    print(flight_price_confirmed)
    new_price = flight_offer[0]['price']['total']
    new_currency = flight_offer[0]["price"]["currency"]
    arrival_iata_code = flight_offer[0]['itineraries'][0]['segments'][0]['arrival']['iataCode']
    departure_iata_code = flight_offer[0]['itineraries'][0]['segments'][0]['departure']['iataCode']

    context = { 'new_price': new_price,
                'new_currency': new_currency,
                'departure_iata_code': departure_iata_code,
                'arrival_iata_code': arrival_iata_code,
                'flight_price_confirmed': flight_price_confirmed
                }
    return render(request, "demo/travelerinfo.html", context)


# We shall call this page later
def final_booking(request):
    if request.method == 'POST':
        print("we have arrived")
        flight_price_confirmed = request.POST.get("flight_price_confirmed")
        flight_price_confirmed = ast.literal_eval(flight_price_confirmed)
        # # Create a fake traveler profile for booking
        # traveler = {
        #     "id": "1",
        #     "dateOfBirth": "1982-01-16",
        #     "name": {"firstName": "DERRICK", "lastName": "MUGALYA"},
        #     "gender": "MALE",
        #     "contact": {
        #         "emailAddress": "mugalyaderrick@gmail.com",
        #         "phones": [
        #             {
        #                 "deviceType": "MOBILE",
        #                 "countryCallingCode": "256",
        #                 "number": "755645169",
        #             }
        #         ],
        #     },
        #     "documents": [
        #         {
        #             "documentType": "PASSPORT",
        #             "birthPlace": "Madrid",
        #             "issuanceLocation": "Madrid",
        #             "issuanceDate": "2015-04-14",
        #             "number": "00000000",
        #             "expiryDate": "2025-04-14",
        #             "issuanceCountry": "ES",
        #             "validityCountry": "ES",
        #             "nationality": "ES",
        #             "holder": True,
        #         }
        #     ],
        # }

        traveler = {
            "id": "1",
            "dateOfBirth": request.POST.get("dateOfBirth"),
            "name": {"firstName": request.POST.get("firstName"), "lastName": request.POST.get("lastName")},
            "gender": request.POST.get("gender"),
            "contact": {
                "emailAddress": request.POST.get("emailAddress"),
                "phones": [
                    {
                        "deviceType": request.POST.get("deviceType"),
                        "countryCallingCode": request.POST.get("countryCallingCode"),
                        "number":request.POST.get("phone_number"),
                    }
                ],
            },
            "documents": [
                {
                    "documentType": request.POST.get("documentType"),
                    "birthPlace": request.POST.get("birthPlace"),
                    "issuanceLocation": request.POST.get("issuanceLocation"),
                    "issuanceDate": request.POST.get("issuanceDate"),
                    "number": request.POST.get("documentNumber"),
                    "expiryDate": request.POST.get("expiryDate"),
                    "issuanceCountry": request.POST.get("issuanceCountry"),
                    "validityCountry": request.POST.get("validityCountry"),
                    "nationality": request.POST.get("nationality"),
                    "holder": True,
                }
            ],
        }
        # print(traveler)
        try:
            order = amadeus.booking.flight_orders.post(
                flight_price_confirmed, traveler
            ).data
            print("First booking call successfull")
        except (ResponseError, KeyError, AttributeError) as error:
            messages.add_message(
                request, messages.ERROR, error.response.result["errors"][0]["detail"]
            )
            print("We have an error on the booking call")
            print(messages.ERROR)
            print("  --  ")
            return render(request, "demo/book_flight.html", {})

        passenger_name_record = []
        booking = Booking(order).construct_booking()
        passenger_name_record.append(booking)
        passenger_details = passenger_name_record.append(booking)
        print("Flight booked successfully")
        print("passeger_details:", passenger_details)
        # print(booking)
        print("Traveller booking list below")
        merged_data = {
            **traveler,
            **booking,
        }

        # Append merged dictionary to a list
        result_list = [merged_data]
        phone_data = merged_data.get("contact", {}).get("phones", [{}])[0]
        document_data = merged_data.get("documents", [{}])[0]
        print("issance location", document_data.get("issuanceLocation"))
        
        # Save data to database
        try:
            Traveler.objects.create(
                price = merged_data.get('price'),
                created = merged_data.get('created'),
                reference = merged_data.get('reference'),
                confirmed = merged_data.get('confirmed'),
                first_name_flight = merged_data.get('first_name'),
                last_name_flight = merged_data.get('last_name'),
                first_flight_departure_airport = merged_data.get('0firstFlightDepartureAirport'),
                first_flight_airline_logo = merged_data.get('0firstFlightAirlineLogo'),
                first_flight_airline = merged_data.get('0firstFlightAirline'),
                first_flight_departure_date = merged_data.get('0firstFlightDepartureDate'),
                departure_date = merged_data.get('0departureDate'),
                first_flight_arrival_airport = merged_data.get('0firstFlightArrivalAirport'),
                first_flight_arrival_date = merged_data.get('0firstFlightArrivalDate'),

                # Traveler personal information
                # self.id = traveler_data.get("id")
                date_of_birth = merged_data.get("dateOfBirth"),
                first_name = merged_data.get("name", {}).get("firstName"),
                last_name = merged_data.get("name", {}).get("lastName"),
                gender = merged_data.get("gender"),
                email_address = merged_data.get("contact", {}).get("emailAddress"),

                # Phones
                # phone_data = merged_data.get("contact", {}).get("phones", [{}])[0]
                device_type = phone_data.get("deviceType"),
                country_calling_code = phone_data.get("countryCallingCode"),
                phone_number = phone_data.get("number"),

                # Documents
                # document_data = merged_data.get("documents", [{}])[0]
                document_type = document_data.get("documentType"),
                birth_place = document_data.get("birthPlace"),
                issuance_location = document_data.get("issuanceLocation"),
                issuance_date = document_data.get("issuanceDate"),
                document_number = document_data.get("number"),
                expiry_date = document_data.get("expiryDate"),
                issuance_country = document_data.get("issuanceCountry"),
                validity_country = document_data.get("validityCountry"),
                nationality = document_data.get("nationality"),
                holder = document_data.get("holder")
            )
            print('Saved to database')
        except Exception as e:
            print('Error' + str(e))

        # Output the result list
        print(result_list)
        # print(mer)
        # return render(request, "demo/book_flight.html")   
        return render(request, "demo/book_flight.html", {"response": passenger_name_record})
    else:
        return render(request, 'demo/book_flight.html')


def origin_airport_search(request):
    if request.is_ajax():
        try:
            data = amadeus.reference_data.locations.get(
                keyword=request.GET.get("term", None), subType=Location.ANY
            ).data
        except (ResponseError, KeyError, AttributeError) as error:
            messages.add_message(
                request, messages.ERROR, error.response.result["errors"][0]["detail"]
            )
    return HttpResponse(get_city_airport_list(data), "application/json")


def destination_airport_search(request):
    if request.is_ajax():
        try:
            data = amadeus.reference_data.locations.get(
                keyword=request.GET.get("term", None), subType=Location.ANY
            ).data
        except (ResponseError, KeyError, AttributeError) as error:
            messages.add_message(
                request, messages.ERROR, error.response.result["errors"][0]["detail"]
            )
    return HttpResponse(get_city_airport_list(data), "application/json")


def get_city_airport_list(data):
    result = []
    for i, val in enumerate(data):
        result.append(data[i]["iataCode"] + ", " + data[i]["name"])
    result = list(dict.fromkeys(result))
    return json.dumps(result)


def travelerinfo(request):
    # Retrieve data from the UI form
    return render(request, "demo/travelerinfo.html")


#. Create a method that receives payment details and returns the pesapal iframe url
# views.py
# from django.views.generic import TemplateView
# from django_pesapal.views import PaymentRequestMixin

class PaymentView(PaymentRequestMixin, TemplateView):
    template_name = "demo/pesapal.html"
    print("before calling api")

    def post(self, request, *args, **kwargs):
        # Handle the form submission here if needed
        print("at post request")
        return super().post(request, *args, **kwargs)

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

    def get_pesapal_payment_iframe(self):
        order_info = {
            'first_name': 'Mugalya ',
            'last_name': 'Derrick',
            'amount': 100,
            'description': 'Payment for X',
            'reference': 20,  # some object id
            'email': 'mugalyaderrick@gmail.com',
        }
        print("Request Parameters:", order_info)
        try:
            iframe_src_url = self.get_payment_url(**order_info)
            # Debugging output
            print("Pesapal API Response:", iframe_src_url)
            return iframe_src_url
        except Exception as e:
            print('error', e)








# class PaymentView(TemplateView, PaymentRequestMixin):
# def get_pesapal_payment_iframe():
#     '''
#     Authenticates with pesapal to get the payment iframe src
#     '''

#     order_info = {
#     'amount': 100,
#     'description': 'Payment for X',
#     'reference': 2, # some object id
#     'email': 'user@example.com'
#     }

#     iframe_src_url = get_payment_url(**order_info)
#     return iframe_src_url

# class PaymentView(PaymentRequestMixin, TemplateView):
#     print("This has been gone through")

#     template_name = "demo/pesapal.html"

#     def get_pesapal_payment_iframe(self):

#         '''
#         Authenticates with pesapal to get the payment iframe src
#         '''

#         order_info = {
#             'first_name': 'Mugalya ',
#             'last_name': 'Derrick',
#             'amount': 100,
#             'description': 'Payment for X',
#             'reference': 20,  # some object id
#             'email': 'mugalyaderrick@gmail.com',
#         }

#         iframe_src_url = self.get_payment_url(**order_info)
#         return iframe_src_url
    

    # def post(self):
    #     #post method request logic here
    #     print("This is the post request")
    

    # get_pesapal_payment_iframe()




# class PaymentView(TemplateView, PaymentRequestMixin):
#     """
#     Make payment view
#     """

#     template_name = "demo/pesapal.html"

#     def get_context_data(self, **kwargs):
#         ctx = super(PaymentView, self).get_context_data(**kwargs)

#         order_info = {
#             "amount": 10,
#             "description": "Payment for X",
#             "reference": 2,
#             "email": "pesapal@example.com",
#         }

#         ctx["pesapal_url"] = self.get_payment_url(**order_info)
#         return ctx


# class PaymentView(PaymentRequestMixin, TemplateView):
#     template_name = "demo/pesapal.html"

#     def get_pesapal_payment_iframe(self):

#         '''
#         Authenticates with pesapal to get the payment iframe src
#         '''
#         order_info = {
#             'first_name': 'Some',
#             'last_name': 'User',
#             'amount': 100,
#             'description': 'Payment for X',
#             'reference': 2,  # some object id
#             'email': 'user@example.com',
#         }

#         iframe_src_url = self.get_payment_url(**order_info)
#         return iframe_src_url



