"""
    Product related endpoints. Included contexts for principles such as
    categories and image processing.
"""

from flask import render_template, session, flash, request, redirect, Blueprint

from models.products.product import Product
from models.stats import Stats
from controllers.database.product import ProductController
from controllers.database.category import CategoryController
from controllers.database.stats import StatsController

from datetime import datetime
from utils.file_utils import save_image, remove_file
from utils.user_utils import is_role

import os

blueprint = Blueprint("products", __name__, url_prefix="/products")


@blueprint.context_processor
def category_list():
    """ Places a list of all categories in the products context """
    database = CategoryController()
    categories = database.read_all()
    return dict(categories=categories)


@blueprint.route('/')
def index():
    """ The front product page """
    # Returning an empty category acts the same
    # as a generic home page
    return category("")


@blueprint.route('/<string:category>')
def category(category: str):
    """ Loads a given categories page """
    database = ProductController()

    # Check to see if there is a custome search term
    search_term = request.args.get("search", type=str)
    if search_term is not None:
        products = database.read_all(category, search_term)
    else:
        products = database.read_all(category)

    # No Products visible
    if products is None:
        flash(
            f"No Products available. Try expanding your search criteria.",
            "warning"
        )

    return render_template(
        'index.html',
        content="content.html",
        products=products,
        category=category
    )


@blueprint.route('/<int:id>')
def id(id: int):
    """ Loads a given product based on ID """
    db = ProductController()
    product = db.read_id(id)

    # Check that a valid product was returned
    if product is None:
        flash(f"No Product available with id {id}", "warning")
        return redirect("/")

    # Record a view on the product
    db = StatsController()
    user_id = session.get('user_id')
    print(user_id)
    db.create(Stats(product.id, user_id))

    return render_template(
        'index.html',
        content='product.html',
        product=product
    )


@blueprint.route('/add')
def display_add_product():
    """ Launches the page to add a new product to the site """
    # User needs to be logged in as a seller to view this page
    if not is_role("Seller"):
        flash("You must be logged in as a seller to view this page!", "error")
        return redirect("/")

    return render_template('index.html', content='new_product.html')


@blueprint.post('/add')
def add_product():
    """ Server site processing to handle a request to add a
        new product to the site
    """
    user_id = session.get('user_id')

    # User needs to be logged in as a seller to view this page
    if not is_role("Seller"):
        flash("You must be logged in as a seller to view this page!", "error")
        return redirect("/")

    file = request.files.get('image')
    image_filename = save_image(file)

    product = Product(
        request.form.get('name'),
        image_filename if image_filename is not None else "",
        request.form.get('description'),
        request.form.get('cost'),
        request.form.get('category'),
        user_id,
        datetime.now(),
        request.form.get('quantity')
    )

    db = ProductController()
    db.create(product)

    return redirect('/products/ownproducts')


@blueprint.post('/update/<int:id>')
def update_product(id: int):
    """ Processes a request to update a product in place on the site """
    # Ensure that the product belongs to the current user
    user_id = session.get('user_id')

    # User needs to be logged in as a seller to view this page
    if not is_role("Seller"):
        flash("You must be logged in as a seller to view this page!", "error")
        return redirect("/")

    db = ProductController()
    product = db.read_id(id)

    if product.sellerID != user_id:
        flash("This product does not belong to you!", "error")
        return redirect("/products/ownproducts")

    # Save new image file
    file = request.files.get('image')
    new_image = save_image(file)

    if new_image is not None:
        remove_file(os.path.join(os.environ.get('FILESTORE'), product.image))
        product.image = new_image

    # Update product details
    product.name = request.form.get('name')
    product.description = request.form.get('description')
    product.category = request.form.get('category')
    product.cost = request.form.get('cost')
    product.quantityAvailable = request.form.get('quantity')

    db.update(product)
    flash("Product successfully updated", 'notice')
    return redirect(f"/products/{product.id}")


@blueprint.post('/delete/<int:id>')
def delete_product(id: int):
    """ Processes a request to delete a product in place on the site """
    # Ensure that the product belongs to the current user
    user_id = session.get('user_id')

    # User needs to be logged in as a seller to view this page
    if not is_role("Seller"):
        flash("You must be logged in as a seller to view this page!", "error")
        return redirect("/")

    db = ProductController()
    product = db.read_id(id)

    if product.sellerID != user_id:
        flash("This product does not belong to you!", "error")
        return redirect("/products/ownproducts")

    db.delete(id)
    flash("Product Removed!", "success")
    return redirect("/products/ownproducts")


@blueprint.route('/ownproducts')
def display_own_products():
    """ Display products owned by the currently logged in seller """
    user_id = session.get('user_id')

    # User must be logged in as seller to view page
    if not is_role("Seller"):
        flash("You must be logged in as a seller to view this page!", "error")
        return redirect("/")

    db = ProductController()
    products = db.read_user(user_id)

    if products is None:
        flash("You don't currently have any products for sale.", "info")

    return render_template(
        'index.html',
        content='content.html',
        products=products
    )
