import os
from datetime import datetime
from urllib.parse import quote_plus
from flask import (Flask, render_template, request, redirect,
                   url_for, flash, session, jsonify)
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from functools import wraps

app = Flask(__name__)
app.secret_key = os.environ.get('SECRET_KEY', 'tccp-secret-key-change-in-production')
basedir = os.path.abspath(os.path.dirname(__file__))

DEFAULT_ADMIN_USERNAME = os.environ.get('ADMIN_USERNAME', 'admin')
DEFAULT_ADMIN_PASSWORD = os.environ.get('ADMIN_PASSWORD', 'tccp2024')


def build_database_uri():
    database_url = os.environ.get('DATABASE_URL')
    if database_url:
        return database_url

    db_host = os.environ.get('DB_HOST') or os.environ.get('MYSQL_HOST')
    db_port = os.environ.get('DB_PORT', '3306')
    db_name = os.environ.get('DB_NAME') or os.environ.get('MYSQL_DATABASE')
    db_user = os.environ.get('DB_USER') or os.environ.get('MYSQL_USER')
    db_password = os.environ.get('DB_PASSWORD') or os.environ.get('MYSQL_PASSWORD')

    if db_host and db_name and db_user is not None and db_password is not None:
        return (
            f"mysql+pymysql://{quote_plus(db_user)}:{quote_plus(db_password)}"
            f"@{db_host}:{db_port}/{db_name}?charset=utf8mb4"
        )

    return 'sqlite:///' + os.path.join(basedir, 'database.db')


app.config['SQLALCHEMY_DATABASE_URI'] = build_database_uri()
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
    'pool_pre_ping': True,
    'pool_recycle': 280,
}
db = SQLAlchemy(app)

# --- MODELS ---
class Admin(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password_hash = db.Column(db.String(200), nullable=False)
    def set_password(self, pw):
        self.password_hash = generate_password_hash(pw)
    def check_password(self, pw):
        return check_password_hash(self.password_hash, pw)

class Quote(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.Text, nullable=False)
    author = db.Column(db.String(150), default='')
    is_active = db.Column(db.Boolean, default=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

class ContactMessage(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), nullable=False)
    email = db.Column(db.String(200), nullable=False)
    subject = db.Column(db.String(300), default='')
    message = db.Column(db.Text, nullable=False)
    is_read = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

# --- AUTH ---
def admin_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        if not session.get('admin_logged_in'):
            return redirect(url_for('admin_login'))
        return f(*args, **kwargs)
    return decorated

# --- PUBLIC ROUTES ---
@app.route('/')
def index():
    quote = Quote.query.filter_by(is_active=True).order_by(Quote.created_at.desc()).first()
    return render_template('index.html', quote=quote)

@app.route('/about')
def about():
    return render_template('about.html')

@app.route('/services')
def services():
    return render_template('services.html')

@app.route('/impact')
def impact():
    return render_template('impact.html')

@app.route('/team')
def team():
    return render_template('team.html')

@app.route('/contact', methods=['GET', 'POST'])
def contact():
    if request.method == 'POST':
        msg = ContactMessage(
            name=request.form['name'].strip(),
            email=request.form['email'].strip(),
            subject=request.form.get('subject', '').strip(),
            message=request.form['message'].strip()
        )
        db.session.add(msg)
        db.session.commit()
        flash('Thank you! We will get back to you soon.', 'success')
        return redirect(url_for('contact'))
    return render_template('contact.html')

@app.route('/api/quote')
def api_quote():
    q = Quote.query.filter_by(is_active=True).order_by(Quote.created_at.desc()).first()
    if q:
        return jsonify({'text': q.text, 'author': q.author})
    return jsonify({'text': '', 'author': ''})

# --- ADMIN ROUTES ---
@app.route('/admin/login', methods=['GET', 'POST'])
def admin_login():
    if session.get('admin_logged_in'):
        return redirect(url_for('admin_dashboard'))
    if not Admin.query.first():
        a = Admin(username=DEFAULT_ADMIN_USERNAME)
        a.set_password(DEFAULT_ADMIN_PASSWORD)
        db.session.add(a)
        db.session.commit()
    if request.method == 'POST':
        u = request.form.get('username', '').strip()
        p = request.form.get('password', '')
        admin = Admin.query.filter_by(username=u).first()
        if admin and admin.check_password(p):
            session['admin_logged_in'] = True
            session['admin_username'] = admin.username
            flash('Welcome back!', 'success')
            return redirect(url_for('admin_dashboard'))
        flash('Invalid credentials.', 'danger')
    return render_template('admin/login.html')

@app.route('/admin/logout')
def admin_logout():
    session.pop('admin_logged_in', None)
    return redirect(url_for('index'))

@app.route('/admin')
@admin_required
def admin_dashboard():
    quotes = Quote.query.order_by(Quote.created_at.desc()).all()
    messages = ContactMessage.query.order_by(ContactMessage.created_at.desc()).limit(20).all()
    unread = ContactMessage.query.filter_by(is_read=False).count()
    return render_template('admin/dashboard.html', quotes=quotes, messages=messages, unread=unread)

@app.route('/admin/quote/add', methods=['POST'])
@admin_required
def admin_quote_add():
    text = request.form.get('text', '').strip()
    author = request.form.get('author', '').strip()
    if text:
        Quote.query.update({Quote.is_active: False})
        db.session.add(Quote(text=text, author=author, is_active=True))
        db.session.commit()
        flash('Quote published!', 'success')
    return redirect(url_for('admin_dashboard'))

@app.route('/admin/quote/<int:qid>/activate', methods=['POST'])
@admin_required
def admin_quote_activate(qid):
    Quote.query.update({Quote.is_active: False})
    Quote.query.get_or_404(qid).is_active = True
    db.session.commit()
    flash('Quote activated.', 'success')
    return redirect(url_for('admin_dashboard'))

@app.route('/admin/quote/<int:qid>/delete', methods=['POST'])
@admin_required
def admin_quote_delete(qid):
    db.session.delete(Quote.query.get_or_404(qid))
    db.session.commit()
    flash('Quote deleted.', 'info')
    return redirect(url_for('admin_dashboard'))

@app.route('/admin/message/<int:mid>/read', methods=['POST'])
@admin_required
def admin_message_read(mid):
    ContactMessage.query.get_or_404(mid).is_read = True
    db.session.commit()
    return redirect(url_for('admin_dashboard'))

@app.route('/admin/password', methods=['POST'])
@admin_required
def admin_change_password():
    a = Admin.query.filter_by(username=session.get('admin_username')).first()
    if a and a.check_password(request.form.get('old_password', '')):
        a.set_password(request.form['new_password'])
        db.session.commit()
        flash('Password changed.', 'success')
    else:
        flash('Current password incorrect.', 'danger')
    return redirect(url_for('admin_dashboard'))

# --- INIT ---
with app.app_context():
    db.create_all()
    if not Quote.query.first():
        db.session.add(Quote(
            text="Mental health is not a destination, but a process. It's about how you drive, not where you're going.",
            author="Noam Shpancer", is_active=True))
        db.session.commit()
    if not Admin.query.first():
        admin = Admin(username=DEFAULT_ADMIN_USERNAME)
        admin.set_password(DEFAULT_ADMIN_PASSWORD)
        db.session.add(admin)
        db.session.commit()

if __name__ == '__main__':
    app.run(debug=True, port=5001)
