import os
import re
import logging
from decouple import config
from moviepy.editor import VideoFileClip
from django.contrib.auth.models import User
from django.http import JsonResponse , Http404
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.shortcuts import render, redirect
from django.views import View

import boto
import boto.s3.connection
import time

from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response

from .models import File, Transcripts
from .utils import generate_name, handle_uploaded_file
from .serializers import FileSerializer,TranscriptsSerializer

logger = logging.getLogger(__file__)


class ListTranscripts(View):
    @method_decorator(login_required(login_url='/auth/login'))
    def get(self, request):
        transcripts=None
        if request.user.is_superuser:
            transcripts = Transcripts.objects.all()
        else :
            transcripts = Transcripts.objects.filter(file_org__user=request.user)
        logger.info(transcripts)
        context = {
            "transcripts":transcripts,
            "page":"allTranscripts"
        }

        return render(request, 'dashboard.html', context)

    @method_decorator(login_required(login_url='/auth/login'))
    def post(self, request):
        if not request.user.is_authenticated:
            return redirect("accounts:login")



@login_required(login_url='/auth/login')
def upload(request):
    if not request.user.is_authenticated:
        return redirect("accounts:login")
    if request.method == 'POST' and ( 'filename' in request.FILES ):
        filename= request.FILES['filename'].name
        content = request.FILES['filename']
        path="media/"
        if not os.path.exists(path):
            os.makedirs(path)
        # generate unique name
        generated_name = generate_name(filename, "en-es-subs")

        # handle upload file to local server
        handle_uploaded_file(content, path, generated_name)

        # save file info in database
        video_path = path+generated_name
        clip = VideoFileClip(video_path)
        filename, extension = os.path.splitext(filename)
        # Create File Object & Save IT
        new_file = File(
            file_title    = filename,
            video_path    = video_path,
            duration      = clip.duration,
            extension     = extension,
            size          = os.path.getsize(video_path),
            user          = request.user
        )
        new_file.save()

        # Create an S3 client object using the Boto3 library
        conn = boto.s3.connect_to_region(
            region_name = config("AWS_REGION", default="us-west-2", cast=str),
            aws_access_key_id = config("AWS_ACCESS_KEY_ID", default="AKIAT6THLFM7NTAL4XWX", cast=str),
            aws_secret_access_key = config("AWS_SECRET_ACCESS_KEY", default="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", cast=str),
            calling_format = boto.s3.connection.OrdinaryCallingFormat(),
        )
        # Try to get the bucket by name
        bucket = conn.get_bucket('input-transcribe-bucket')
        # Create a new Key object that can be used to interact with a new uploaded file to the bucket.
        k = bucket.new_key(generated_name)
        # start Uploading File To The Buket With The Created Key.
        k.set_contents_from_filename(video_path)
        time.sleep(5)
        # remove file from local server
        os.remove(video_path)

        return render(
            request ,
            "upload.html",
            {
                'id_file':new_file.id_file,
                'page':'upload'
            }
        )
    return render(
        request ,
        "upload.html",
        {
            'page':'upload'
        }
    )

@login_required(login_url='/auth/login')
def transcript_status(request, id_file):
    try:
        file = File.objects.get(id_file=id_file)
        file_lang = file.language
        transcript = Transcripts.objects.get(file_org=file)

        if ("en" in file_lang and transcript.path_srt_es) or ("es" in file_lang and transcript.path_srt_en):
            return JsonResponse({
                'status': 2,
                'detail': 'Transcript Found With All Info',
                'message': 'Your file has been processed completely.',
                'transcript': TranscriptsSerializer(transcript).data
            })
        else:
            # If the transcripts are still being processed, return a message
            return JsonResponse({
                'status': 1,
                'detail': 'Transcript Found With Initial Creation',
                'message': 'Please wait, your file is processing right now.',
                'transcript': TranscriptsSerializer(transcript).data
            })
    except Transcripts.DoesNotExist:
        return JsonResponse({
            'status': 0,
            'detail': 'Transcript Not Found',
            'message': 'Please wait, your file is uploading/processing right now.',
            'transcript': ''
        })

class S3Input(APIView):
    # authentication_classes = [TokenAuthentication]  # Token authentication is required for this view
    # permission_classes = [IsOwnerOrReadOnly]  # Only the owner can modify the File object, others can only read
    def get_object(self, id):
        """
        Helper method to retrieve a File object by UUID in name.
        """
        # Returns the File object with the given uuid contains in video_path
        try:
            return File.objects.get(video_path__contains=id)
        except File.DoesNotExist:
            # Raises 404 error if no Transcripts objects are found
            raise Http404


    def get(self, request):
        """
        Handles GET requests to retrieve all the File objects in the database.
        Returns a JSON response with the serialized data.
        """
        # Retrieves all File objects and returns them in a response
        queryset = File.objects.filter(user=request.user)
        serializer = FileSerializer(queryset, many=True)

        return Response(serializer.data, status.HTTP_200_OK)

    def put(self, request):
        """
        Handles PUT requests to update a File object in the database.
        Expects the request object to have file_s3_url, language, and srt_file fields.
        """
        #
        BASE_S3_URL = 'https://input-transcribe-bucket.s3.us-east-2.amazonaws.com/'
        # Retrieves the file_uuid using the uuid in the request data file_s3_url
        file_uuid = str(request.data.get('file_s3_url')).replace(BASE_S3_URL,'')
        # Retrieves the file language using the language attribute in the request data
        file_lang = str(request.data.get('language'))
        # get file instance based on file_name
        original_file = self.get_object(file_uuid)
        # Retrieves the corresponding File object and updates it with the request data
        file_serializer = FileSerializer(original_file,data=request.data)
        if file_serializer.is_valid(raise_exception=True):
            file_serializer.save()
            # rename file with langauage tag
            # file_name = f"{file_lang}_{file_uuid}.srt"
            # Create A New Transcripts object For The Updated File
            transcript = Transcripts(file_org=original_file)
            if 'en' in file_lang:
                transcript.path_srt_en = request.data.get('srt_file')
            if 'es' in file_lang:
                transcript.path_srt_es = request.data.get('srt_file')
            transcript.save()
            # Run Celery Task With Transcript ID

            return Response(file_serializer.data, status=status.HTTP_201_CREATED)
        return Response(file_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class S3Output(APIView):
    # authentication_classes = [TokenAuthentication]  # Token authentication is required for this view
    # permission_classes = [IsOwnerOrReadOnly]  # Only the owner can modify the File object, others can only read
    def get_objects(self):
        # Returns all Transcripts objects
        try:
            return Transcripts.objects.all()
        except Transcripts.DoesNotExist:
            # Raises 404 error if no Transcripts objects are found
            raise Http404

    def get_object(self, id):
        # Returns the Transcripts object with the given file_org id
        try:
            return Transcripts.objects.get(file_org=id)
        except Transcripts.DoesNotExist:
            # Raises 404 error if the Transcripts object is not found
            raise Http404

    def get(self, request):
        # Retrieves all Transcripts objects and returns them in a response
        queryset = self.get_objects()
        serializer = TranscriptsSerializer(queryset, many=True)
        return Response(data=serializer.data, status=status.HTTP_200_OK)

    def put(self, request):
        # Retrieves the file_id using the uuid in the request data
        file_uuid = str(request.data.get('file')).split(".")[0]
        # print("DATA EXAMPLE: ",request.data)
        # print("File UUID: ",file_uuid)
        file_id = File.objects.get(video_path__contains=file_uuid)

        # Retrieves the corresponding Transcripts object and updates it with the request data
        transcript = self.get_object(file_id)
        transcript_serializer = TranscriptsSerializer(transcript, data=request.data)
        if transcript_serializer.is_valid(raise_exception=True):
            transcript_serializer.save()
            # save_vtt_wget(transcript)
            # download_captions(transcript, request)
            # save_local(request)
            # print(transcript_serializer.data)
            return Response(data=transcript_serializer.data, status=status.HTTP_201_CREATED)
        return Response(data=transcript_serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class SaveSubtitleView(APIView):

    def post(self, request):
        json_data = request.data
        STATIC_FILES = 'static/subtitles'
        # Extract file name and content from the JSON payload
        file_name = json_data['file_name']
        srt_content = json_data['srt']
        vtt_content = json_data['vtt']

        # Write SRT file to static directory
        srt_file_path = os.path.join(STATIC_FILES, "srt", file_name + '.srt')
        with open(srt_file_path, 'w') as srt_file:
            srt_file.write(srt_content)

        # Write VTT file to static directory
        vtt_file_path = os.path.join(STATIC_FILES, "vtt", file_name + '.vtt')
        with open(vtt_file_path, 'w') as vtt_file:
            vtt_file.write(vtt_content)

        return Response({'message': 'Files saved successfully.'})


