from datetime import datetime

from django.views import View
from django.http import JsonResponse
from .models import SessionPurchaseOrder
from .serializers import SessionPurchaseOrderSerializer
from rest_framework import serializers
import json
import stripe
from django.conf import settings
import os
import base64
import re
import requests
import resend

stripe.api_key = settings.STRIPE_SECRET_KEY
resend.api_key = settings.RESEND_API_KEY

# Create your views here.
class ApplySessionPurchaseOrderPayment:
    def convertToLineItems(self,total,description):
        priceData = {
                "price_data":{
                    "currency":"usd",
                    "unit_amount_decimal":round((float(total) * 100)),
                    "product_data":{
                        "name":'Total',
                        "description":description,
                    }
                },
                "quantity":1
            }
        
        lineItems = [
            priceData
        ]

        return lineItems
    
    def pay(self,keyName,price,quantity,successURL,cancelURL):
        total = 0
        total = price * quantity

        lineItems = self.convertToLineItems(total,keyName)
        
        sessionPurchaseOrder = SessionPurchaseOrder(
            total = total,
            productDescription = keyName,
            createdDate = datetime.now(),
            updatedDate = datetime.now(),
            status = 'pending',
            sessionId = '',
            sessionUrl = '',
            isFileDownloaded = False,
            email = '',
        )

        if sessionPurchaseOrder.id is not None:
            raise serializers.ValidationError({"error": ["Error creating purchase order"]})
        
        sessionIdPurchaseOrderId = None
        sessionPurchaseOrder.save()
        sessionIdPurchaseOrderId = sessionPurchaseOrder.id

        checkoutSession = stripe.checkout.Session.create(
                            payment_method_types=["card"],
                            line_items=lineItems,
                            mode="payment",
                            success_url=successURL + '&sessionpurchaseorderid='+str(sessionIdPurchaseOrderId),
                            cancel_url=cancelURL + '&sessionpurchaseorderid='+str(sessionIdPurchaseOrderId),
                        )
        
        sessionPurchaseOrder.sessionId = checkoutSession.id
        sessionPurchaseOrder.sessionUrl = checkoutSession.url
        sessionPurchaseOrder.save()
        ser = SessionPurchaseOrderSerializer(sessionPurchaseOrder)
        return JsonResponse({"url":checkoutSession.url,"id":sessionPurchaseOrder.id},safe=False)

    def expire(self):
        return True

class CreateStripeCheckoutSessionPurchaserOrderView(View):
    def post(self,request,*args,**kwargs):

        keyName = None
        price = None
        quantity = None
        apiKey = request.headers.get("apiKey",None)
        if apiKey is None:
            raise serializers.ValidationError({"error": ["apiKey header is required"]})
        
        if apiKey != settings.SECRET_KEY:
            raise serializers.ValidationError({"error": ["apiKey header is invalid"]})
        
        jsonData = json.loads(request.body)

        if jsonData.__len__() > 0:
            if "keyName" in jsonData:
                keyName = jsonData["keyName"]
                if keyName not in ["starter","pro","premium"]:
                    raise serializers.ValidationError({"error": ["Invalid KeyName"]})

            if "price" in jsonData:
                price = jsonData["price"]
                if price <= 0:
                    raise serializers.ValidationError({"error": ["Price must be greater than 0"]})
            if "quantity" in jsonData:
                quantity = jsonData["quantity"]
                if quantity <= 0:
                    raise serializers.ValidationError({"error": ["Quantity must be greater than 0"]})
            
            applyPayment = ApplySessionPurchaseOrderPayment()
            return applyPayment.pay(keyName,price,quantity,settings.PAYMENT_SUCCESS_PURCHASE_ORDER_WEB_URL,settings.PAYMENT_CANCEL_PURCHASE_ORDER_WEB_URL)
        else:
            raise serializers.ValidationError({"error": ["Request body is empty"]})

class ExpireStripeCheckoutSessionPurchaseOrderView(View):
    def post(self,request,*args,**kwargs):
        applyPayment = ApplySessionPurchaseOrderPayment()
        isSuccess = applyPayment.expire()
        return JsonResponse({"url":"",},safe=False)


class SendFileView(View):
    def extract_file_id(self,drive_url):
        """Extract the file ID from a Google Drive share URL."""
        match = re.search(r"/d/([a-zA-Z0-9_-]+)", drive_url)
        if match:
            return match.group(1)
        match = re.search(r"id=([a-zA-Z0-9_-]+)", drive_url)
        if match:
            return match.group(1)
        raise ValueError("Could not extract file ID from URL")
    
    def download_from_drive(self,drive_url):
        """Download a publicly shared Google Drive file. Returns (filename, bytes)."""
        file_id = self.extract_file_id(drive_url)
        url = f"https://drive.google.com/uc?export=download&id={file_id}"

        session = requests.Session()
        response = session.get(url, stream=True)

        # For larger files, Drive shows a virus-scan warning — handle the confirm token
        for key, value in response.cookies.items():
            if key.startswith("download_warning"):
                response = session.get(url, params={"confirm": value}, stream=True)
                break

        # Sometimes the confirm token is in the HTML body instead of cookies
        if "text/html" in response.headers.get("Content-Type", ""):
            match = re.search(r'name="confirm"\s+value="([^"]+)"', response.text)
            if match:
                response = session.get(url, params={"confirm": match.group(1)}, stream=True)

        response.raise_for_status()

        # Try to get filename from Content-Disposition header
        filename = f"file_{file_id}"
        cd = response.headers.get("Content-Disposition", "")
        match = re.search(r'filename="([^"]+)"', cd)
        if match:
            filename = match.group(1)

        return filename, response.content

    def getFileByUrl(self,drive_url,to_email):
        #print("Downloading file from Google Drive...")
        filename, file_bytes = self.download_from_drive(drive_url)
        #print(f"Got: {filename} ({len(file_bytes)} bytes)")

        try:
            result = resend.Emails.send({
                "from": os.environ.get("EMAIL_FROM", "Your File <onboarding@snowflakeco.com>"),
                "to": [to_email],
                "subject": f"File from Google Drive: {filename}",
                "html": f"<h1>Your attachment is ready</h1><p>Please find <strong>{filename}</strong> attached.</p>",
                "attachments": [
                    {
                        "filename": filename,
                        "content": base64.b64encode(file_bytes).decode(),
                    },
                ],
            })
            #print("Email sent!")
            #print(f"Email ID: {result['id']}")
            return True
        except Exception as e:
            print(f"Error: {e}")
        
        return False
            
    def post(self,request,*args,**kwargs):
        apiKey = request.headers.get("apiKey",None)
        if apiKey is None:
            raise serializers.ValidationError({"error": ["apiKey header is required"]})
        
        if apiKey != settings.SECRET_KEY:
            raise serializers.ValidationError({"error": ["apiKey header is invalid"]})
        
        jsonData = json.loads(request.body)

        sessionPurchaseOrderId = None
        email = "whassanin@gmail.com"

        if jsonData.__len__() > 0:
            if "id" in jsonData:
                sessionPurchaseOrderId = jsonData["id"]
            else:
                raise serializers.ValidationError({"error": ["id is required in the request body"]})

            if "email" in jsonData:
                email = jsonData["email"]
            else:
                raise serializers.ValidationError({"error": ["email is required in the request body"]})

            dataList = SessionPurchaseOrder.objects.filter(id=sessionPurchaseOrderId)
            if dataList.__len__() > 0:
                selected = dataList[0]
                session = stripe.checkout.Session.retrieve(selected.sessionId)
                if session.payment_status == "paid":
                    if selected.isFileDownloaded == False:
                        filePath = None
                        if selected.productDescription == "starter":
                            filePath = settings.STARTERPACK
                        elif selected.productDescription == "pro":
                            filePath = settings.PROPACK
                        elif selected.productDescription == "premium":
                            filePath = settings.PREMIUMPACK
                        else:
                            raise serializers.ValidationError({"error": ["Invalid Pack Selection"]})

                        if filePath is not None:
                            isSent = self.getFileByUrl(filePath,email)
                            if isSent == True:
                                selected.isFileDownloaded = True
                                selected.email = email
                                selected.save()
                                return JsonResponse({"sendFileStatus":"sent","id":sessionPurchaseOrderId,"email":email})
                            else:
                                raise serializers.ValidationError({"error": ["File already Sent"]})
                        else:
                            raise serializers.ValidationError({"error": ["File Path Not Found"]})
                    else:
                        return JsonResponse({"message":"File has already been downloaded"},safe=False)
                else:
                    raise serializers.ValidationError({"error": ["No Payments made"]})    
            else:
                raise serializers.ValidationError({"error": ["SessionPurchaseOrder with the given ID does not exist"]})

        return JsonResponse({"message":"File downloaded and emailed successfully"},safe=False)
