from textwrap import wrap
import io
from datetime import datetime, date
from typing import List
import requests

from fastapi import APIRouter, HTTPException, File, UploadFile, Form
from fastapi.responses import FileResponse, JSONResponse

from pydantic import BaseModel

from minio import Minio
import Minio_Storage

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib.utils import ImageReader
from reportlab.platypus import SimpleDocTemplate

from supertokens_python.recipe.session.framework.fastapi import verify_session
from supertokens_python.recipe.session import SessionContainer
from fastapi import Depends

import Minio_Storage.minioConnection


router = APIRouter()

class minioPullRequest(BaseModel):
    file_path: str

class minioDeleteRequest(BaseModel):
    file_path: str

class medCertUploud(BaseModel):
    app_id: str
    fullName: str 
    id_no: str 
    docfname: str 
    busName: str 
    busAddr: str 
    busNo: str 
    busEmail: str 
    startDate: str 
    endDate: str 
    returnDate: str 
    logo_path: str
    sig_path: str

class perscription(BaseModel):
    name: str
    unit: str
    form: str
    fullForm: str
    quantity: str
    dosage: str
    times: str
    days: str
    repeats: str

class perscriptionList(BaseModel):
    app_id: str
    fullName: str 
    id_no: str 
    docfname: str 
    busName: str 
    busAddr: str 
    busNo: str 
    busEmail: str  
    logo_path: str
    sig_path: str
    data: List[perscription]

@router.get("/minio/pull/file/{app_id}/{folder}/{file_name}/{env}", tags=["Minio"])
async def pull_File_from_user(app_id: str, folder: str, file_name: str, env: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
    path = app_id + "/" + folder + "/" + file_name
    try:
        # uploudFile(app_id, file.filename, extension[1], content)
        client = Minio_Storage.minioConnection.minioConnect(env)
    
        miniourl = client.presigned_get_object("mih", path)
        # temp = minioResponse.data#.encode('utf-8').strip()
        # print(temp)
        # print("=======================================================================")
        # temp = temp.decode('utf-8')
        #print(miniourl)
    except Exception as error:
        raise HTTPException(status_code=404, detail=miniourl)
        # return {"message": error}
    return {
        "minioURL": miniourl,
    }

@router.post("/minio/upload/file/", tags=["Minio"])
async def upload_File_to_user(file: UploadFile = File(...), app_id: str= Form(...), folder: str= Form(...), session: SessionContainer = Depends(verify_session())):
    extension = file.filename.split(".")
    content = file.file 
    try:
        uploudFile(app_id, folder, file.filename, extension[1], content)
    except Exception as error:
        raise HTTPException(status_code=404, detail="Failed to Uploud Record")
    return {"message": "Successfully Delete File"}
    
    # return {
    #     "app_id": app_id,
    #     "file name": file.filename,
    #     "extension": extension[0],
    #     "file contents": file.file.read(),
    # }

@router.delete("/minio/delete/file/", tags=["Minio"])
async def delete_File_of_user(requestItem: minioDeleteRequest, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
    path = requestItem.file_path
    try:
        # uploudFile(app_id, file.filename, extension[1], content)
        client = Minio_Storage.minioConnection.minioConnect("dev")
    
        minioError = client.remove_object("mih", path)
    except Exception as error:
        raise HTTPException(status_code=404, detail=minioError)
        # return {"message": error}
    return {"message": "Successfully deleted File"}
    # return {
    #     "app_id": app_id,
    #     "file name": file.filename,
    #     "extension": extension[0],
    #     "file contents": file.file.read(),
    # }

# Get List of all files by patient
@router.post("/minio/generate/med-cert/", tags=["Minio"])
async def upload_med_cert_to_user(requestItem: medCertUploud, session: SessionContainer = Depends(verify_session())):
    uploudMedCert(requestItem)
    return {"message": "Successfully Generated File"}

@router.post("/minio/generate/perscription/", tags=["Minio"])
async def upload_perscription_to_user(requestItem: perscriptionList, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
    uploudPerscription(requestItem)
    return {"message": "Successfully Generated File"}

def uploudFile(app_id, folder, fileName, extension, content):
    client = Minio_Storage.minioConnection.minioConnect("dev")
    found = client.bucket_exists("mih")
    if not found:
        client.make_bucket("mih")
    else:
        print("Bucket already exists")
    fname = app_id + "/" + folder + "/" + fileName
    client.put_object("mih", 
                    fname, 
                    content, 
                    length=-1,
                    part_size=10*1024*1024,
                    content_type=f"application/{extension}")
        

def uploudMedCert(requestItem: medCertUploud):
    client = Minio_Storage.minioConnection.minioConnect("dev")
    generateMedCertPDF(requestItem)
    today = datetime.today().strftime('%Y-%m-%d')
    found = client.bucket_exists("mih")
    if not found:
        client.make_bucket("mih")
    else:
        print("Bucket already exists")
    fileName = f"{requestItem.app_id}/patient_files/Med-Cert-{requestItem.fullName}-{today}.pdf"
    client.fput_object("mih", fileName, "temp-med-cert.pdf")

def generateMedCertPDF(requestItem: medCertUploud):
    client = Minio_Storage.minioConnection.minioConnect("dev")
    new_logo_path = requestItem.logo_path.replace(" ","-")
    new_sig_path = requestItem.sig_path.replace(" ","-")
    minioLogo = client.get_object("mih", new_logo_path).read()
    imageLogo = ImageReader(io.BytesIO(minioLogo))
    minioSig = client.get_object("mih", new_sig_path).read()
    imageSig = ImageReader(io.BytesIO(minioSig))
    w,h = A4
    today = datetime.today().strftime('%d-%m-%Y')
    myCanvas = canvas.Canvas("temp-med-cert.pdf", pagesize=A4)

    #Business Logo
    myCanvas.drawImage(imageLogo, 50, h - 125,100,100, mask='auto')

    #Business Details
    myCanvas.setFont('Helvetica-Bold', 10)
    myCanvas.drawRightString(w - 50,h - 40, f"Name: {requestItem.busName}")
    myCanvas.drawRightString(w - 50,h - 55, f"Address: {requestItem.busAddr}")
    myCanvas.drawRightString(w - 50,h - 70, f"Contact No.: {requestItem.busNo}")
    myCanvas.drawRightString(w - 50,h - 85, f"Email: {requestItem.busEmail}")
    myCanvas.line(50,h-150,w-50,h-150)
    #Todays Date
    myCanvas.setFont('Helvetica', 12)
    issueDate =  str(today)
    myCanvas.drawRightString(w - 50,h - 180,issueDate)

    #Title
    myCanvas.setFont('Helvetica-Bold', 20)
    myCanvas.drawString(w-375, h - 200, "Medical Certificate")

    #Body
    myCanvas.setFont('Helvetica', 12)
    body = ""
    body += "This is to certify that " + requestItem.fullName.upper() + " (" + requestItem.id_no+ ") was seen by " + requestItem.docfname.upper() + " on " + requestItem.startDate + "."
    body += "\nHe/She is unfit to attend work/school from " + requestItem.startDate + " up to and including " + requestItem.endDate + "."
    body += "\nHe/She will return on " + requestItem.returnDate + "."
    
    y = 250
    for line in wrap(body, 90):
        myCanvas.drawString(50, h-y, line)
        y += 30
    # myCanvas.drawString(50, h-250,line1)
    # myCanvas.drawString(50, h-280,line2)
    # myCanvas.drawString(50, h-310,line3)

    #Signature
    myCanvas.drawImage(imageSig, 50, h - 690,100,100)
    myCanvas.line(50,h-700,200,h-700)
    myCanvas.drawString(50, h-720, requestItem.docfname.upper())

    #QR Verification
    qrText = requestItem.fullName.upper() + " booked off from " + requestItem.startDate + " to " + requestItem.endDate + " by " + requestItem.docfname.upper() + ".\nPowered by Mzansi Innovation Hub."
    qrText = qrText.replace(" ","+")
    
    url = f"https://api.qrserver.com/v1/create-qr-code/?data={qrText}&size=100x100"
    response = requests.get(url)
    image = ImageReader(io.BytesIO(response.content))
    myCanvas.drawImage(image,w-150, h-700,100,100)

    myCanvas.setFont('Helvetica-Bold', 15)
    myCanvas.drawString(w-150,h-720,"Scan to verify")

    myCanvas.save()

def uploudPerscription(requestItem: perscriptionList):
    client = Minio_Storage.minioConnection.minioConnect("dev")
    generatePerscriptionPDF(requestItem)
    today = datetime.today().strftime('%Y-%m-%d')
    found = client.bucket_exists("mih")
    if not found:
        client.make_bucket("mih")
    else:
        print("Bucket already exists")
    fileName = f"{requestItem.app_id}/patient_files/Perscription-{requestItem.fullName}-{today}.pdf"
    client.fput_object("mih", fileName, "temp-perscription.pdf")    

def generatePerscriptionPDF(requestItem: perscriptionList):
    client = Minio_Storage.minioConnection.minioConnect("dev")
    new_logo_path = requestItem.logo_path.replace(" ","-")
    new_sig_path = requestItem.sig_path.replace(" ","-")
    minioLogo = client.get_object("mih", new_logo_path).read()
    imageLogo = ImageReader(io.BytesIO(minioLogo))
    minioSig = client.get_object("mih", new_sig_path).read()
    imageSig = ImageReader(io.BytesIO(minioSig))
    w,h = A4
    
    
    myCanvas = canvas.Canvas("temp-perscription.pdf", pagesize=A4)

    #Business Logo
    myCanvas.drawImage(imageLogo, 50, h - 125,100,100, mask='auto')

    #Business Details
    myCanvas.setFont('Helvetica-Bold', 10)
    myCanvas.drawRightString(w - 50,h - 40, f"Name: {requestItem.busName}")
    myCanvas.drawRightString(w - 50,h - 55, f"Address: {requestItem.busAddr}")
    myCanvas.drawRightString(w - 50,h - 70, f"Contact No.: {requestItem.busNo}")
    myCanvas.drawRightString(w - 50,h - 85, f"Email: {requestItem.busEmail}")
    myCanvas.line(50,h-150,w-50,h-150)
    #Todays Date
    myCanvas.setFont('Helvetica', 12)
    today = datetime.today()
    issueDate =  today.strftime('%d-%m-%Y')
    myCanvas.drawRightString(w - 50,h - 180,issueDate)

    #Title
    myCanvas.setFont('Helvetica-Bold', 20)
    myCanvas.drawString(w-375, h - 200, "Perscription")

    #Body
    myCanvas.setFont('Helvetica-Bold', 12)
    myCanvas.drawString(50, h-250, f"Patient: {requestItem.fullName}")
    myCanvas.drawString(50, h-270, f"Patient ID: {requestItem.id_no}")
    
    #boday headings 
    myCanvas.drawString(50, h-300, "Description")
    myCanvas.drawRightString(w - 50, h-300, "Repeat(s)")
    myCanvas.drawRightString(w - 150, h-300, "Quantity")
    myCanvas.line(50,h-310,w-50,h-310)

    myCanvas.setStrokeColorRGB(0.749, 0.749, 0.749)
    myCanvas.setFont('Helvetica', 12)
    y = 330
    i = 0
    for persc in requestItem.data:
        description1 = f"{persc.name} - {persc.form}"
        description2 = f"{persc.dosage} {persc.fullForm}, {persc.times} time(s) daily, for {persc.days} day(s)"
        quant = f"{persc.quantity}"
        reps = f"{persc.repeats}"

        myCanvas.drawString(50, h-y, f"{i+1}.")
        myCanvas.drawString(60, h-y, description1)
        myCanvas.drawRightString(w-75, h-y, reps)
        myCanvas.drawRightString(w-175, h-y, quant)
        y+=15
        myCanvas.drawString(60, h-y, description2)
        if(i<len(requestItem.data)-1):
            y+=10
            myCanvas.line(50,h-y,w-50,h-y)
        y += 20
        i+=1
    myCanvas.setStrokeColorRGB(0,0,0)
    myCanvas.line(50,h-y-10,w-50,h-y-10)


    #Signature
    y=750
    myCanvas.drawImage(imageSig, 50, h-y,100,100)
    myCanvas.line(50,h-y-10,200,h-y-10)
    myCanvas.drawString(50, h-y-30, requestItem.docfname.upper())

    #QR Verification
    qrText = f"Perscription generated on {issueDate} by {requestItem.docfname} for {requestItem.fullName}.\nPowered by Mzansi Innovation Hub."
    qrText = qrText.replace(" ","+")
    
    url = f"https://api.qrserver.com/v1/create-qr-code/?data={qrText}&size=100x100"
    response = requests.get(url)
    image = ImageReader(io.BytesIO(response.content))
    myCanvas.drawImage(image,w-150, h-y-10,100,100)

    myCanvas.setFont('Helvetica-Bold', 15)
    myCanvas.drawString(w-150,h-y-30,"Scan to verify")

    myCanvas.save()

def byteToMb(size):
    sizekb = size /1000
    sizemb = sizekb / 1000
    return sizemb

# print(byteToMb(229574))