# 3RD PARTY IMPORTS
from flask import (
    Blueprint, request, render_template, session, jsonify, current_app, send_from_directory
    )
import math
import postsqldb
import mimetypes
import os
import pprint

# APPLICATION IMPORTS
import webpush
from application.access_module import access_api
from application import postsqldb, database_payloads
from application.receipts import receipts_processes, receipts_database


receipt_api = Blueprint('receipt_api', __name__, template_folder='templates', static_folder='static')


# ROOT TEMPLATE ROUTES
@receipt_api.route("/")
@access_api.login_required
def receipts():
    sites = [site[1] for site in postsqldb.get_sites(session['user']['sites'])]
    return render_template("receipts_index.html", current_site=session['selected_site'], sites=sites)

@receipt_api.route("/<id>")
@access_api.login_required
def receipt(id):
    sites = [site[1] for site in postsqldb.get_sites(session['user']['sites'])]
    units = postsqldb.get_units_of_measure()
    return render_template("receipt.html", id=id, current_site=session['selected_site'], sites=sites, units=units)


# API ROUTES
@receipt_api.route('/api/getItems', methods=["GET"])
@access_api.login_required
def getItems():
    recordset = []
    count = {'count': 0}
    if request.method == "GET":
        page = int(request.args.get('page', 1))
        limit = int(request.args.get('limit', 10))
        site_name = session['selected_site']
        offset = (page - 1) * limit
        search_string = f"%{str(request.args.get('search_string', ""))}%"
        sort_order = "item_name ASC"
        payload = (search_string, limit, offset, sort_order)
        recordset, count = receipts_database.getItemsWithQOH(site_name, payload)
        return jsonify({"items":recordset, "end":math.ceil(count['count']/limit), "error":False, "message":"items fetched succesfully!"})
    return jsonify({"items":recordset, "end":math.ceil(count['count']/limit), "error":True, "message":"There was an error with this GET statement"})

@receipt_api.route('/api/getVendors', methods=["GET"])
@access_api.login_required
def getVendors():
    recordset = []
    count = 0
    if request.method == "GET":
        page = int(request.args.get('page', 1))
        limit = int(request.args.get('limit', 10))
        site_name = session['selected_site']
        offset = (page - 1) * limit
        recordset, count = receipts_database.paginateVendorsTuples(site_name, payload=(limit, offset))
        return jsonify({"vendors":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"})
    return jsonify({"vendors":recordset, "end":math.ceil(count/limit), "error":True, "message":"There was an error with this GET statement"})

@receipt_api.route('/api/getLinkedLists', methods=["GET"])
@access_api.login_required
def getLinkedLists():
    recordset = []
    count = 0
    if request.method == "GET":
        page = int(request.args.get('page', 1))
        limit = int(request.args.get('limit', 10))
        site_name = session['selected_site']
        offset = (page - 1) * limit
        recordset, count = receipts_database.paginateLinkedLists(site_name, payload=(limit, offset))
        return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":False, "message":"items fetched succesfully!"})
    return jsonify({"items":recordset, "end":math.ceil(count/limit), "error":True, "message":"There was an error with this GET statement"})

@receipt_api.route('/api/getReceipts', methods=["GET"])
@access_api.login_required
def getReceipts():
    recordset = []
    if request.method == "GET":
        page = int(request.args.get('page', 1))
        limit = int(request.args.get('limit', 50))
        offset = (page - 1) * limit
        site_name = session['selected_site']
        recordset, count = receipts_database.paginateReceiptsTuples(site_name, payload=(limit, offset))
        return jsonify({'receipts':recordset, "end": math.ceil(count/limit), 'error': False, "message": "Get Receipts Successful!"})
    return jsonify({'receipts': recordset, "end": math.ceil(count/limit), 'error': True, "message": "Something went wrong while getting receipts!"})

@receipt_api.route('/api/getReceipt', methods=["GET"])
@access_api.login_required
def getReceipt():
    receipt = []
    if request.method == "GET":
        receipt_id = int(request.args.get('id', 1))
        site_name = session['selected_site']
        receipt = receipts_database.getReceiptByID(site_name, (receipt_id, ))
        return jsonify({'receipt': receipt, 'error': False, "message": "Get Receipts Successful!"})
    return jsonify({'receipt': receipt,  'error': True, "message": "Something went wrong while getting receipts!"})

@receipt_api.route('/api/addReceipt', methods=["POST", "GET"])
@access_api.login_required
def addReceipt():
    if request.method == "GET":
        user_id = session['user_id']
        site_name = session['selected_site']
        receipt = database_payloads.ReceiptPayload(
            receipt_id=f"PR-{receipts_database.requestNextReceiptID(site_name)}",
            submitted_by=user_id
        )
        receipts_database.insertReceiptsTuple(site_name, receipt.payload())
        return jsonify({'error': False, "message": "Receipt Added Successful!"})
    return jsonify({'error': True, "message": "Something went wrong while adding receipt!"})

@receipt_api.route('/api/addSKULine', methods=["POST"])
@access_api.login_required
def addSKULine():
    if request.method == "POST":
        item_id = int(request.get_json()['item_id'])
        receipt_id = int(request.get_json()['receipt_id'])
        print(item_id, receipt_id)
        site_name = session['selected_site']
        item = receipts_database.getItemAllByID(site_name, (item_id, ))
        data = {
            'cost': item['item_info']['cost'],
            'expires': item['food_info']['expires']
        }
        receipt_item = database_payloads.ReceiptItemPayload(
            type="sku",
            receipt_id=receipt_id,
            barcode=item['barcode'],
            item_uuid=item['item_uuid'],
            name=item['item_name'],
            qty=item['item_info']['uom_quantity'],
            uom=item['item_info']['uom']['id'],
            data=data
        )
        receipts_database.insertReceiptItemsTuple(site_name, receipt_item.payload())
        return jsonify({'error': False, "message": "Line added Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while add SKU line!"})

@receipt_api.route('/api/addCustomLine', methods=["POST"])
@access_api.login_required
def addCustomLine():
    if request.method == "POST":
        receipt_id = int(request.get_json()['receipt_id'])
        site_name = session['selected_site']
        print(receipt_id)
        data = {
            'cost': request.get_json()['line_cost'],
            'expires': False
        }

        receipt_item = database_payloads.ReceiptItemPayload(
            type="custom",
            receipt_id=receipt_id,
            barcode=None,
            item_uuid=None,
            name=request.get_json()['line_name'],
            qty=request.get_json()['line_qty'],
            uom=request.get_json()['line_UOM'],
            data=data
        )
        receipts_database.insertReceiptItemsTuple(site_name, receipt_item.payload())
        return jsonify({'error': False, "message": "Line added Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while add SKU line!"})


@receipt_api.route('/api/deleteLine', methods=["POST"])
@access_api.login_required
def deleteLine():
    if request.method == "POST":
        line_id = int(request.get_json()['line_id'])
        site_name = session['selected_site']
        receipts_database.deleteReceiptItemsTuple(site_name, (line_id, ))
        return jsonify({'error': False, "message": "Line Deleted Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while deleting line!"})

@receipt_api.route('/api/denyLine', methods=["POST"])
@access_api.login_required
def denyLine():
    if request.method == "POST":
        line_id = int(request.get_json()['line_id'])
        site_name = session['selected_site']
        receipts_database.updateReceiptItemsTuple(site_name, {'id': line_id, 'update': {'status': 'Denied'}})
        return jsonify({'error': False, "message": "Line Denied Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while denying line!"})

@receipt_api.route('/api/saveLine', methods=["POST"])
@access_api.login_required
def saveLine():
    if request.method == "POST":
        line_id = int(request.get_json()['line_id'])
        payload = request.get_json()['payload']
        site_name = session['selected_site']
        receipt_item = receipts_database.selectReceiptItemsTuple(site_name, (line_id, ))
        if 'api_data' in receipt_item['data'].keys():
            payload['data']['api_data'] = receipt_item['data']['api_data']
        receipts_database.updateReceiptItemsTuple(site_name, {'id': line_id, 'update': payload})
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})

@receipt_api.route('/api/postLinkedItem', methods=["POST"])
@access_api.login_required
def postLinkedItem():
    if request.method == "POST":
        receipt_item_id = int(request.get_json()['receipt_item_id'])
        link_list_id = int(request.get_json()['link_list_id'])
        conv_factor = float(request.get_json()['conv_factor'])

        site_name = session['selected_site']
        user_id = session['user_id']

        payload = {
            'receipt_item_id': receipt_item_id,
            'linked_list_id': link_list_id,
            'conv_factor': conv_factor
        }

        receipts_processes.linkItem(site_name, user_id, payload)
            
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})

@receipt_api.route('/api/saveBarcodeLink', methods=["POST"])
@access_api.login_required
def saveBarcodeLink():
    if request.method == "POST":
        print(request.get_json())
        site_name = session['selected_site']    
        user_id = session['user_id']
        receipts_processes.linkBarcodeToItem(site_name, user_id, request.get_json())
        #receipts_processes.linkItem(site_name, user_id, payload)
            
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})

@receipt_api.route('/api/resolveLine', methods=["POST"])
@access_api.login_required
def resolveLine():
    if request.method == "POST":
        line_id = int(request.get_json()['line_id'])
        site_name = session['selected_site']
        user_id = session['user_id']
        payload = {'line_id': line_id}
        receipts_processes.postLine(site_name, user_id, payload)
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})

@receipt_api.route('/api/resolveServiceLine', methods=["POST"])
@access_api.login_required
def resolveServiceLine():
    if request.method == "POST":
        line_id = int(request.get_json()['line_id'])
        site_name = session['selected_site']
        user_id = session['user_id']
        payload = {'line_id': line_id}
        receipts_processes.postService(site_name, user_id, payload)
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})

@receipt_api.route('/api/postVendorUpdate', methods=["POST"])
@access_api.login_required
def postVendorUpdate():
    if request.method == "POST":
        receipt_id = int(request.get_json()['receipt_id'])
        vendor_id = int(request.get_json()['vendor_id'])
        site_name = session['selected_site']
        receipts_database.updateReceiptsTuple(site_name, {'id': receipt_id, 'update': {'vendor_id': vendor_id}})
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})

@receipt_api.route('/api/resolveReceipt', methods=["POST"])
@access_api.login_required
def resolveReceipt():
    if request.method == "POST":
        receipt_id = int(request.get_json()['receipt_id'])
        site_name = session['selected_site']
        user= session['user']
        receipt = receipts_database.updateReceiptsTuple(site_name, {'id': receipt_id, 'update': {'receipt_status': 'Resolved'}})
        webpush.push_ntfy(title=f"Receipt '{receipt['receipt_id']}' Resolved", body=f"Receipt {receipt['receipt_id']} was completed by {user['username']}.")
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})

@receipt_api.route('/api/uploadfile/<receipt_id>', methods=["POST"])
@access_api.login_required
def uploadFile(receipt_id):
    file = request.files['file']
    file_path = current_app.config['FILES_FOLDER'] + f"/receipts/{file.filename.replace(" ", "_")}"
    file.save(file_path)
    file_type, _ = mimetypes.guess_type(file.filename)
    preview_image = ""
    if file_type == "application/pdf":
        output_path = f"{current_app.config['FILES_FOLDER']}/receipts/previews/"
        preview_image = receipts_processes.create_pdf_preview(file_path, output_path)

    file_size = os.path.getsize(file_path)
    site_name = session['selected_site']
    username = session['user']['username']
    receipt_files = receipts_database.selectReceiptsTuple(site_name, (receipt_id, ))['files']
    receipt_files[file.filename.replace(" ", "_")] = {'file_path': file.filename.replace(" ", "_"), 'file_type': file_type, 'file_size': file_size, 'uploaded_by': username, 'preview_image': preview_image}
    receipts_database.updateReceiptsTuple(site_name, {'id': receipt_id, 'update': {'files': receipt_files}})
    return jsonify({})

@receipt_api.route('/api/getFile/<file_name>')
@access_api.login_required
def getFile(file_name):
    path_ = current_app.config['FILES_FOLDER'] + "/receipts"
    print(path_)
    return send_from_directory(path_, file_name)

@receipt_api.route('/api/getPreview/<file_name>')
@access_api.login_required
def getPreview(file_name):
    path_ = current_app.config['FILES_FOLDER'] + "/receipts/previews"
    return send_from_directory(path_, file_name)

@receipt_api.route('/api/checkAPI', methods=["POST"])
@access_api.login_required
def checkAPI():
    if request.method == "POST":
        line_id = int(request.get_json()['line_id'])
        barcode = request.get_json()['barcode']
        site_name = session['selected_site']
        api_response, api_data = receipts_processes.get_open_facts(barcode)
        if api_response:
            receipt_item = receipts_database.selectReceiptItemsTuple(site_name, (line_id, ))
            item_data = receipt_item['data']
            item_data['api_data'] = api_data
            payload = {'id': line_id, 'update': {'type': 'api','data': item_data,'name': api_data['product_name']}}
            receipts_database.updateReceiptItemsTuple(site_name, payload)
            return jsonify({'error': False, "message": "Line updated for API, Succesfully"})
        else:
            return jsonify({'error': True, "message": "Item not in WorldFoodFacts!"})
        return jsonify({'error': False, "message": "Line Saved Succesfully"})
    return jsonify({'error': True, "message": "Something went wrong while saving line!"})