import os
from flask import request, render_template, make_response, redirect, session, flash
from flask_login import login_required, logout_user, login_user, current_user, login_manager
from datetime import datetime as dt
from flask import current_app as app
from .models import db, Users, notes, lists_tbl, cow_list, breeder_tag_cow_details, hc_cow_details, ip_address, open_ai_haro
from .forms import LoginForm, CowDataEntryForm
from werkzeug.security import check_password_hash, generate_password_hash
from slugify import slugify
import uuid
from werkzeug.utils import secure_filename
from datetime import datetime
import requests
import openai
import re


def is_admin():
    curr_user = current_user.get_id()
    user_record = Users.query.filter_by(id = curr_user).first()
    is_admin = user_record.admin
    return is_admin

def add_years(d, years):
    """Return a date that's `years` years after the date (or datetime)
    object `d`. Return the same calendar date (month and day) in the
    destination year, if it exists, otherwise use the following day
    (thus changing February 29 to March 1).

    """
    try:
        return d.replace(year = d.year + years)
    except ValueError:
        return d + (date(d.year + years, 1, 1) - date(d.year, 1, 1))    

@app.template_filter('reformat_date')
def reformat_date(this_date):
    this_date = datetime.strptime(this_date, '%Y-%m-%d')
    return this_date.strftime("%d-%m-%Y")

@app.template_filter('left_of_overview')
def left_of_overview(overview):
    if len(overview) > 150:
        overview = overview[0:150] + "..."
    return overview


@app.login_manager.user_loader
def load_user(id):
    """Check if user is logged-in on every page load."""
    if id is not None:
        return Users.query.get(id)
    return None

@app.route('/logip')
def logip():
    this_ip_address = request.remote_addr

    logged_on = datetime.today()
    logged_on = logged_on.strftime('%Y-%m-%d')    
    #with open('iplog.txt', 'w') as f:
    #    f.write(ip_address)

    new_ip_address = ip_address(
        ip_address = this_ip_address,
        dt_stamp=logged_on 
    )

    db.session.add(new_ip_address)
    db.session.commit() 

    return(this_ip_address)

@app.route('/showips')
def showips():
    ip_addresses = ip_address.query.all()
    return render_template('showips.html', ip_addys = ip_addresses)
    

@app.route('/')
def index():
    cowNumber = request.args.get('cowNumber')
    if cowNumber is None:
        return("hi")
    #print(cowNumber)
    if cowNumber.isnumeric():
        herdcompanion_info = hc_cow_details.query.filter_by(cow_number = cowNumber).first()
        breeder_tag_info = breeder_tag_cow_details.query.filter_by(cow_id = cowNumber).first()
        this_cow_notes = notes.query.filter_by(cow_id = cowNumber).order_by(notes.note_log_date.desc())
        this_cow_lists = db.session.query(cow_list, lists_tbl).join(cow_list).filter_by(cow_id = cowNumber, hidden=0)
        #print(this_cow_lists.lists_tbl.list_name)
        form = CowDataEntryForm()
        return render_template('index.html', herdcompanion_info = herdcompanion_info, cowNumber = cowNumber, breeder_tag_info = breeder_tag_info, this_cow_lists = this_cow_lists, cow_notes = this_cow_notes, user_logged_in=current_user.is_authenticated, form=form)
    else:
        return("opps that's not a cow number!")

@app.route('/lists')
def lists():
    all_lists = lists_tbl.query.all()
    return render_template('lists.html', all_lists = all_lists, user_logged_in=current_user.is_authenticated)

@app.route('/search', methods=['GET', 'POST'])
def search():
    this_query = request.form["searchbox"]
    if this_query.isnumeric():
        return redirect("/?cowNumber=" + this_query)
    else:
        return ("hi")
    
@app.route('/addcowlist', methods=['POST'])
def addcowlist():
    this_query = request.form["addcow"]
    this_list = request.form["this_list"]
    if this_query.isnumeric() and this_list.isnumeric():
        new_cow_list = cow_list(

            cow_id = this_query,
            list_id = this_list,
            hidden = 0
        )
        db.session.add(new_cow_list)
        db.session.commit() 
        return redirect("/lists/" + str(this_list))
    else:
        return ("looks like some text was entered when it should have been a cow ID? ")
@app.route('/addlist', methods=['POST'])
def addlist():
    this_query = request.form["addlist"]
    new_list = lists_tbl(

        list_name = this_query,
        hidden = 0
    )
    db.session.add(new_list)
    db.session.commit() 
    return redirect("/lists")

@app.route('/lists/<int:list_id>')
def this_list(list_id):
    this_list_name = lists_tbl.query.filter_by(id = list_id).first()
    this_list = cow_list.query.filter_by(list_id = list_id, hidden=0)
    return render_template('thislist.html', this_list = this_list, this_list_name=this_list_name, user_logged_in=current_user.is_authenticated)

@app.route('/hideevent/<int:event_id>')
def hide_event(event_id):
    this_list = notes.query.filter_by(id = event_id).first()
    this_list.hidden = 1
    db.session.commit()

    return redirect('/dashboard')

@app.route('/removefromlist/<int:cow_list_id>-<int:list_id>')
def remove_from_list(cow_list_id, list_id):
    this_list = cow_list.query.filter_by(id = cow_list_id).first()
    this_list.hidden = 1
    db.session.commit()

    return redirect('/lists/' + str(list_id))

@app.route('/note')
def note():
    return("hi -coming soon")

@app.route('/add-event', methods=['GET', 'POST'])
def add_event():
    form = CowDataEntryForm()
    cowNumber = form.cowNumber.data
    #note_type = form.note_type.data
    #note_text = form.note_text.data
    #note_log_date = form.note_log_date.data
    created_on = datetime.today()
    created_on = created_on.strftime('%Y-%m-%d')

    #print(cowNumber)
    #print(note_type)
    #print(note_text)
    #print(note_log_date)

    new_event = notes(
        cow_id = form.cowNumber.data,
        note_log_date = form.note_log_date.data,
        created_on = created_on,
        note_type = form.note_type.data,
        user_id = 1,
        note_text = form.note_text.data,
        hidden = 0

    )
    db.session.add(new_event)
    db.session.commit() 
    if form.validate_on_submit():
        print("through form validation")

        return redirect('/?cowNumber=' + cowNumber)
    else:
        print("form validation failed soz")
    






@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    print(form.username.data)
    print(form.password.data)
    print(form.validate_on_submit())
    
    if form.validate_on_submit():
        print("through form valiation")
        user = Users.query.filter_by(username=form.username.data).first()
        #print(user.password)
        if user:
            if check_password_hash(user.password, form.password.data):
                session['username'] = form.username.data
                login_user(user)
                
                return redirect('/dashboard')
            else:
                return redirect("/login")
        else:
            return redirect("/login")
    return render_template('login.html', form=form, user_logged_in=current_user.is_authenticated)


@app.route('/dashboard')
#@login_required
def dashboard():
    #print(current_user.get_id())
    #TODO - are we going to allow multiple listings on same login - this .first is only going to allow 1
    user_is_admin = 1 #is_admin()
    this_late_availability = ""
    #site = sites.query.filter_by(owner_id = current_user.get_id()).first()
    ##if site is not None:
    #    this_late_availability = late_availability.query.filter_by(site_id = site.id, active=1)
    
    events = notes.query.filter_by(hidden=0).order_by(notes.note_log_date.desc())

    #print(site is None)
    #print(site)
    return render_template('dashboard.html',  events = events, user_logged_in=current_user.is_authenticated, user_is_admin= user_is_admin)


@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect('/login')

@app.route('/harodata')
def showme():
    haro_data_records = open_ai_haro.query.all()
    return render_template('harodata.html', haro_data_records = haro_data_records)

@app.route('/haro', methods=['POST'])
def process_request():
    created_on = datetime.today()
    created_on = created_on.strftime('%Y-%m-%d')

    json = request.get_json()
    the_query_email = json["details"]
    
    print(str(the_query_email))
    queries = the_query_email.split("-----------------------------------")


 
    openai.api_key = "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"


    email_pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'

    summary_pattern = r'Summary:(.*)'

    text_pattern = r'^Summary: .*?\n(.*)'

    openai_responses = ""
    for query in queries:
        print(query)
        response = openai.Completion.create(
            model="text-davinci-003",
            prompt="Decide whether the following query is related to camping, glamping or outdoor adventures, I need a True or False as an answer:\n\n---------------------\n\n" + query + "\n-----------------------------------\n\nIs this query related to camping, glamping or outdoor adventures, True or False:",
            temperature=0.7,
            max_tokens=512,
            top_p=1,
            frequency_penalty=0,
            presence_penalty=0
        )
        response_text = response['choices'][0]['text'].strip()
        email = re.search(email_pattern, query)
        query_title = re.search(summary_pattern, query)
        
        if query_title != None:
            query_title = query_title.group(1)
        else:
            query_title = ""

        if email != None:
            this_email = email.group(0)
        else:
            this_email = ""
        
        print(query_title)
        #text = re.search(text_pattern, response_text, re.DOTALL)

        # if the response is yes - we need to hit openai again to generate content
        new_article_to_submit = ""
        print("DO WE WRITE:" + str(response_text).strip())
        if response_text == "True" or response_text == "TRUE":
            do_we_write = 1
        else:
            do_we_write = 0

        print(do_we_write)
        if do_we_write == 1:
            # article_writer = openai.Completion.create(
            #     model="text-davinci-003",
            #     prompt="I need you to write a 300 word article answering the Query and Requirements sections in the following text:\n---------------------\n\n" + query,
            #     temperature=0.7,
            #     max_tokens=512,
            #     top_p=1,
            #     frequency_penalty=0,
            #     presence_penalty=0
            # )
            article_writer2 = openai.ChatCompletion.create(
                model="gpt-3.5-turbo",
                messages=[
                        {"role": "system", "content": "You are an expert copy writer. The user will provide queries from journalists which you will provide answers to based on their query and requirements. The user is called Mark, they are the owner of Somerset Yurts and an outdoor adventure, camping and glamping enthusiast they have a website at www.somersetyurts.co.uk. You need to write the response to the journalist as though you are Mark, the journalist shouldn't know the response is generated by OpenAI. If there are images requested you will response with a suitable prompt to generate the image with openai image generator at the bottom of the response."},
                        {"role": "user", "content": query},
                    ]
                )



            #new_article_to_submit = article_writer['choices'][0]['text']        
            new_article_to_submit = article_writer2['choices'][0]['message']['content']
            print(article_writer2)
            print(new_article_to_submit)
        # log the responses to the database
        new_openai_response = open_ai_haro(
            dt_stamp = created_on,
            query_email = this_email,
            query_summary = query_title,
            query_response = response_text,
            full_query = query,
            response_to_submit = new_article_to_submit.replace("\n", "%0A")

        )

        db.session.add(new_openai_response)
        db.session.commit()         


        openai_responses = openai_responses + response['choices'][0]['text'] + "<br>"

    return render_template('haro.html', json = json, queries = queries, openai_responses = openai_responses)

