from flask import Blueprint, render_template, request, redirect, url_for, flash
from . import db
from .models import Admin, Client, Provision
from werkzeug.security import check_password_hash, generate_password_hash
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from math import ceil
from flask import jsonify
from sqlalchemy import or_, asc, desc, exists
from sqlalchemy.sql import case
from datetime import datetime
admin_bp = Blueprint('admin', __name__)

# Simple admin session demo using a cookie (for demo only)

# Simple helper to send email
def send_email(to_email, subject, body):
    sender_email = "admin@allocai.io"
    sender_password = "kfxwlnvuklmckhxo"
    smtp_server = "smtp.gmail.com"
    smtp_port = 587  # TLS port (use 465 if SSL)

    msg = MIMEMultipart()
    msg['From'] = sender_email
    msg['To'] = to_email
    msg['Subject'] = subject
    msg.attach(MIMEText(body, 'html'))  # use 'html' for styled body

    try:
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.starttls()
        server.login(sender_email, sender_password)
        server.sendmail(sender_email, to_email, msg.as_string())
        server.quit()
        print("✅ Email sent successfully to", to_email)
    except Exception as e:
        print(f"❌ Error sending email: {e}")

@admin_bp.route('/')
def index():
    return redirect(url_for('client.client_login'))


@admin_bp.route('/admin/login', methods=['GET', 'POST'])
def login():
    is_admin = request.cookies.get('is_admin')
    if  is_admin:
         return redirect(url_for('admin.home'))
    if request.method == 'POST':
        email = request.form.get('adminEmail')
        password = request.form.get('adminPassword', '').strip()
        admin = Admin.query.filter_by(email=email).first()
       
        if admin and check_password_hash(admin.password, password):
            
            # set a very simple session indicator
            # in production use flask-login
            resp = redirect(url_for('admin.home'))
            resp.set_cookie('is_admin', '1')
           
            return resp
        else:
            print(f"DEBUG: Login attempt -> email={email}, password={password}")
            flash('Invalid credentials', 'danger')

    return render_template('admin_login.html')


@admin_bp.route('/admin/home')
def home():
    is_admin = request.cookies.get('is_admin')
    if not is_admin:
        return redirect(url_for('admin.login'))

    # COPILOT COUNTS
    copilot_provisioned = Provision.query.filter(
        Provision.features.ilike("%copilot%")
    ).count()

    copilot_active = db.session.query(Client).join(
        Provision, Provision.email == Client.email
    ).filter(
        Provision.features.ilike("%copilot%")
    ).count()

    # ATTRIBUTION COUNTS
    attribution_provisioned = Provision.query.filter(
        Provision.features.ilike("%attribution%")
    ).count()

    attribution_active = db.session.query(Client).join(
        Provision, Provision.email == Client.email
    ).filter(
        Provision.features.ilike("%attribution%")
    ).count()

    return render_template(
        'admin_home.html',
        copilot_provisioned=copilot_provisioned,
        copilot_active=copilot_active,
        attribution_provisioned=attribution_provisioned,
        attribution_active=attribution_active
    )
    


@admin_bp.route('/admin/provision', methods=['GET', 'POST'])
def provision():
    is_admin = request.cookies.get('is_admin')
    if not is_admin:
        return redirect(url_for('admin.login'))

    form_data = {
        "firstName": "",
        "lastName": "",
        "email": "",
        "company": "",
        "jobTitle": "",
        "crm": "",
        "features": [],
        "comments": "",
        "copilot_term": 30,
        "copilot_term_type": "days",
        "attribution_term": 1,
        "attribution_term_type": "years",
        "provisioned_date": datetime.utcnow().strftime("%Y-%m-%d")
    }

    error = None

    if request.method == 'POST':
        form_data.update({
            "firstName": request.form.get('firstName', '').strip(),
            "lastName": request.form.get('lastName', '').strip(),
            "email": request.form.get('email', '').strip(),
            "company": request.form.get('company', '').strip(),
            "jobTitle": request.form.get('jobTitle', '').strip(),
            "crm": request.form.get('crm', ''),
            "features": request.form.getlist('features'),
            "comments": request.form.get('comments', '').strip(),
            "copilot_term": request.form.get("copilot_term"),
            "copilot_term_type": request.form.get("copilot_term_type"),
            "attribution_term": request.form.get("attribution_term"),
            "attribution_term_type": request.form.get("attribution_term_type"),
            "provisioned_date": request.form.get("provisioned_date")
        })

        if Provision.query.filter_by(email=form_data["email"]).first():
            error = "A provision with this email already exists."
            return render_template('admin_provision.html', form_data=form_data, error=error)

        pr = Provision(
            first_name=form_data["firstName"],
            last_name=form_data["lastName"],
            email=form_data["email"],
            company=form_data["company"],
            job_title=form_data["jobTitle"],
            crm=form_data["crm"],
            features=",".join(form_data["features"]),
            comments=form_data["comments"],

            copilot_term=form_data["copilot_term"],
            copilot_term_type=form_data["copilot_term_type"],
            attribution_term=form_data["attribution_term"],
            attribution_term_type=form_data["attribution_term_type"],
            provisioned_date=datetime.strptime(form_data["provisioned_date"], "%Y-%m-%d")
        )

        db.session.add(pr)
        db.session.commit()


        # 🔧 Helpers to format trial terms dynamically
        def format_term(amount, unit):
            if not amount or not unit:
                return None

            amount = int(amount) if str(amount).isdigit() else amount

            # Singular word fix
            if amount == 1 and unit.endswith("s"):
                unit = unit[:-1]

            return f"{amount}-{unit.capitalize()}"


        def format_access(amount, unit, product_name):
            formatted_term = format_term(amount, unit)
            if not formatted_term:
                return None
            return f"{formatted_term} Free Trial of {product_name}"

        # Build dynamic access list
        access_items = []

        copilot_access = format_access(
            form_data.get("copilot_term"),
            form_data.get("copilot_term_type"),
            "Alloc AI Strategist Pro"
        )

        attribution_access = format_access(
            form_data.get("attribution_term"),
            form_data.get("attribution_term_type"),
            "Attribution Tool"
        )

        if copilot_access:
            access_items.append(copilot_access)

        if attribution_access:
            access_items.append(attribution_access)

        if not access_items:
            access_items.append("Base Access")

        # Convert into HTML list items
        access_list_html = "".join(f"<li>{item}</li>" for item in access_items)


        # 📩 Build final email
        subject = "Welcome to Alloc AI — Just One Step Left"

        body = f"""
        <html>
        <body style="font-family: Arial, sans-serif; color:#333; line-height:1.6;">
            <p>Hi {form_data["firstName"]},</p>

            <p>Thank you for your interest in Alloc AI. We have provisioned your request.</p>

            <p><strong>Your access includes:</strong></p>
            <ul>
                {access_list_html}
            </ul>

            <p>
                To complete your registration and activate your access, click below:<br>
                <a href="https://copilot.allocai.io/client/login" 
                style="color:#0066cc; font-weight:bold; text-decoration:none;">
                Login to Alloc AI</a>
            </p>

            <p>If you didn’t request this or need help, just reply to this email.</p>

            <p>Thanks,<br><strong>Alloc AI Team</strong></p>
        </body>
        </html>
        """


        send_email(form_data["email"], subject, body)
        

        # ✅ Notify admin as well
        admin_body = f"New provision submitted by {form_data['firstName']} {form_data['lastName']} ({form_data['email']})."
        send_email("admin@allocai.io", "New Provision Request", admin_body)

        flash('Provision request submitted', 'success')
        return redirect(url_for('admin.home'))

    return render_template('admin_provision.html', form_data=form_data, error=error)

@admin_bp.route('/admin/provisionslist')
def provisions_list():
    is_admin = request.cookies.get('is_admin')
    if not is_admin:
        return redirect(url_for('admin.login'))

    page = request.args.get('page', 1, type=int)
    per_page = 10
    search = request.args.get('search', '', type=str)

    query = Provision.query
    if search:
        query = query.filter(
            or_(
                Provision.first_name.ilike(f"%{search}%"),
                Provision.last_name.ilike(f"%{search}%"),
                Provision.email.ilike(f"%{search}%"),
                Provision.company.ilike(f"%{search}%")
            )
        )

    total = query.count()
    provisions = query.order_by(Provision.id.desc()).offset((page-1)*per_page).limit(per_page).all()

    total_pages = ceil(total / per_page)

    return render_template(
        'admin_provisions_list.html',
        provisions=provisions,
        page=page,
        total_pages=total_pages,
        search=search
    )
# 📌 Edit provision
@admin_bp.route('/admin/provision/edit/<int:id>', methods=['GET', 'POST'])
def edit_provision(id):
    is_admin = request.cookies.get('is_admin')
    if not is_admin:
        return redirect(url_for('admin.login'))

    provision = Provision.query.get_or_404(id)

    if request.method == 'POST':
        provision.first_name = request.form.get('firstName')
        provision.last_name = request.form.get('lastName')
        provision.email = request.form.get('email')
        provision.company = request.form.get('company')
        provision.job_title = request.form.get('jobTitle')
        provision.crm = request.form.get('crm')
        provision.features = ','.join(request.form.getlist('features'))
        provision.comments = request.form.get('comments')

        # 🔥 NEW FIELDS — Save them when editing
        provision.provisioned_date = request.form.get('provisioned_date') or provision.provisioned_date
        provision.copilot_term = request.form.get('copilot_term')
        provision.copilot_term_type = request.form.get('copilot_term_type')
        provision.attribution_term = request.form.get('attribution_term')
        provision.attribution_term_type = request.form.get('attribution_term_type')

        db.session.commit()
        flash("Provision updated successfully!", "success")
        return redirect(url_for('admin.provisions_list'))

    # 👇 Send values back to form when editing
    return render_template('admin_provision.html', form_data={
        "firstName": provision.first_name,
        "lastName": provision.last_name,
        "email": provision.email,
        "company": provision.company,
        "jobTitle": provision.job_title,
        "crm": provision.crm,
        "features": provision.features.split(",") if provision.features else [],
        "comments": provision.comments,

        # 🔥 Include new values so form autofills during edit
        "provisioned_date": provision.provisioned_date.strftime("%Y-%m-%d") if provision.provisioned_date else "",
        "copilot_term": provision.copilot_term,
        "copilot_term_type": provision.copilot_term_type,
        "attribution_term": provision.attribution_term,
        "attribution_term_type": provision.attribution_term_type,
    })


# 📌 Delete provision
@admin_bp.route('/admin/provision/delete/<int:id>', methods=['POST'])
def delete_provision(id):
    is_admin = request.cookies.get('is_admin')
    if not is_admin:
        return redirect(url_for('admin.login'))

    provision = Provision.query.get_or_404(id)
    db.session.delete(provision)
    db.session.commit()
    flash("Provision deleted successfully!", "success")
    return redirect(url_for('admin.provisions_list'))

@admin_bp.route('/admin/provisions/data')
def provisions_data():
    is_admin = request.cookies.get('is_admin')
    if not is_admin:
        return jsonify({"error": "Unauthorized"}), 403

    # DataTables variables
    draw = int(request.args.get('draw', 0))
    start = int(request.args.get('start', 0))
    length = int(request.args.get('length', 10))
    search_value = request.args.get('search[value]', '')
    order_col_index = request.args.get('order[0][column]')
    order_dir = request.args.get('order[0][dir]', 'asc')

    # Custom URL query parameters
    feature_filter = request.args.get('feature')  # e.g. copilot
    setup_filter = request.args.get('setup')      # active / inactive

    # For sorting "setup" column
    status_expr = case(
        (exists().where(Client.email == Provision.email), 1),
        else_=0
    )

    # Map DataTables columns → DB fields
    column_map = {
        'setup': status_expr,
        'provisioned_date': Provision.provisioned_date,
        'terms': Provision.id,  # can't sort combined string
        'features': Provision.features,
        'comments': Provision.comments,
        'name': (Provision.last_name, Provision.first_name),
        'email': Provision.email,
        'company': Provision.company,
        'job_title': Provision.job_title,
        'crm': Provision.crm,
        'id': Provision.id
    }

    # Base query
    q = Provision.query
    records_total = q.count()

    # FEATURE FILTER
    if feature_filter:
        q = q.filter(Provision.features.ilike(f"%{feature_filter}%"))

    # SETUP FILTER
    if setup_filter in ("active", "inactive"):
        email_exists = exists().where(Client.email == Provision.email)
        q = q.filter(email_exists if setup_filter == "active" else ~email_exists)

    # SEARCH FILTER
    if search_value:
        s = f"%{search_value}%"
        q = q.filter(
            Provision.first_name.ilike(s) |
            Provision.last_name.ilike(s) |
            Provision.email.ilike(s) |
            Provision.company.ilike(s) |
            Provision.job_title.ilike(s) |
            Provision.crm.ilike(s)
        )

    records_filtered = q.count()

    # SORTING
    order_col = "id"
    if order_col_index is not None:
        col_data = request.args.get(f'columns[{order_col_index}][data]')
        if col_data in column_map:
            order_col = col_data

    sort_target = column_map[order_col]

    if isinstance(sort_target, tuple):
        order_list = [desc(col) if order_dir == 'desc' else asc(col) for col in sort_target]
        q = q.order_by(*order_list)
    else:
        q = q.order_by(desc(sort_target) if order_dir == 'desc' else asc(sort_target))

    # PAGINATION
    provisions = q.offset(start).limit(length).all()

    # RESPONSE DATA
    data = []

    for p in provisions:
        exists_client = db.session.query(
            exists().where(Client.email == p.email)
        ).scalar()

        # Formats
        features_display = p.features.replace(",", ", ") if p.features else ""
        comments_display = (p.comments[:40] + "...") if p.comments and len(p.comments) > 40 else (p.comments or "")
        provision_date = p.provisioned_date.strftime("%Y-%m-%d") if p.provisioned_date else ""

        offer_terms = ""
        if p.copilot_term and p.copilot_term_type:
            offer_terms += f"Copilot: {p.copilot_term} {p.copilot_term_type}"
        if p.attribution_term and p.attribution_term_type:
            offer_terms += f" | Attribution: {p.attribution_term} {p.attribution_term_type}"

        data.append({
            "id": p.id,
            "setup": "Active" if exists_client else "Inactive",
            "provisioned_date": provision_date,
            "terms": offer_terms,
            "features": features_display,
            "name": f"{p.first_name} {p.last_name}",
            "email": p.email,
            "company": p.company,
            "job_title": p.job_title,
            "crm": p.crm,
            "comments": comments_display
        })

    return jsonify({
        "draw": draw,
        "recordsTotal": records_total,
        "recordsFiltered": records_filtered,
        "data": data
    })


@admin_bp.route('/admin/logout')
def logout():
    resp = redirect(url_for('admin.login'))
    resp.delete_cookie('is_admin')
    flash("You have been logged out", "info")
    return resp

@admin_bp.route('/1yearoffer', methods=['GET', 'POST'])
def public_signup():
    form_data = {
        "firstName": "",
        "lastName": "",
        "email": "",
        "company": "",
        "jobTitle": "",
        "crm": "",
        "features": ["copilot", "attribution"],  # forced enabled
        "comments": "",
        "offer_terms": "30-Day Trial + 1-Year Free Offer to Alloc AI Strategist Pro AND 30-Day Trial of Attribution Tool."
    }

    error = None

    if request.method == 'POST':
        form_data.update({
            "firstName": request.form.get('firstName', '').strip(),
            "lastName": request.form.get('lastName', '').strip(),
            "email": request.form.get('email', '').strip(),
            "company": request.form.get('company', '').strip(),
            "jobTitle": request.form.get('jobTitle', '').strip(),
            "crm": request.form.get('crm', ''),
            "comments": request.form.get('comments', '').strip(),
        })

        # Prevent duplicate signup
        if Provision.query.filter_by(email=form_data["email"]).first():
            error = "This email has already been registered."
            return render_template('public_signup.html', form_data=form_data, error=error)

        # Save signup
        new_provision = Provision(
            first_name=form_data["firstName"],
            last_name=form_data["lastName"],
            email=form_data["email"],
            company=form_data["company"],
            job_title=form_data["jobTitle"],
            crm=form_data["crm"],
            features="copilot,attribution",
            comments=form_data["comments"],
            provisioned_date=datetime.utcnow(),
            copilot_term=30,
            copilot_term_type="days",
            attribution_term=1,
            attribution_term_type="years"
        )

        db.session.add(new_provision)
        db.session.commit()

        # -----------------------------
        # 🚀 Send confirmation email
        # -----------------------------
        subject = "Welcome to Alloc AI — Your Access Is Ready"

        body = f"""
        <html>
        <body style="font-family: Arial, sans-serif; line-height:1.6;">
            <p>Hi {form_data["firstName"]},</p>

            <p>Welcome to Alloc AI — we’re excited to have you onboard.</p>

            <p><strong>Your access includes:</strong></p>
            <ul>
                <li>30-Day Free Trial + 1-Year Free Access to Alloc AI Strategist Pro</li>
                <li>30-Day Free Trial of Attribution Tool</li>
            </ul>

              <p>
               Get started here:
                 <a href="https://copilot.allocai.io/client/login" 
                    style="color:#0066cc; font-weight:bold; text-decoration:none;">
                    Login to Alloc AI
                </a>
            </p>

            <p>If you didn’t request this or need help, just reply to this email.</p>

            <p>Thanks,<br><strong>Alloc AI Team</strong></p>
        </body>
        </html>
        """

        send_email(form_data["email"], subject, body)
       
         # ✅ Notify admin as well
        admin_body = f"New provision submitted by {form_data['firstName']} {form_data['lastName']} ({form_data['email']})."
        send_email("admin@allocai.io", "New Provision Request", admin_body)

        flash("Signup received — check your inbox for access instructions.", "success")

        return redirect("/1yearoffer")

    return render_template('public_signup.html', form_data=form_data, error=error)
