import os
import uuid
import sqlite3
import json
import requests
from dotenv import load_dotenv
from flask import request, render_template, redirect, url_for, jsonify, session, flash, abort, g, send_from_directory, send_file, make_response

load_dotenv()
# Read website_url directly from .env — single source of truth
website_url = os.getenv("website_url", "localhost")
from urllib.parse import urlparse
from helpers import (url, _db, get_site_settings, is_human, get_text_overrides,
                     get_page_content, get_page_faqs, normalize_page_id, dir_path,
                     get_client_ip, check_conversion_limit, record_tool_usage,
                     get_current_user)
                     
from converters.screenshot_converter import (
    FORMAT_EXT, SCREENSHOT_DIR,
    create_driver, capture_screenshot_image, apply_scale, save_in_format
)
from converters.image_bg_remove_converter import (
    validate_image, remove_background
)
                     

ALLOWED_DOMAIN = website_url


def _is_allowed_origin(origin):
    if not origin:
        return False
    try:
        from urllib.parse import urlparse as _urlparse
        parsed = _urlparse(origin)
        host = parsed.hostname or ''
        return host == ALLOWED_DOMAIN or host.endswith('.' + ALLOWED_DOMAIN)
    except Exception:
        return False


def replace_url_lang(url_str, lang, full=False):
    from urllib.parse import urlparse as url_parse
    from configs.languages import supported_languages
    
    # Parse URL
    parsed = url_parse(url_str)
    path = parsed.path
    
    # Remove trailing slash (except root)
    if path != '/' and path.endswith('/'):
        path = path.rstrip('/')
    
    # Split path
    paths = path.split("/")
    paths.pop(0)  # Remove empty first element
    
    # Handle language replacement
    if len(paths) > 0 and paths[0] in supported_languages.keys():
        prev = "/" + paths[0]
        next = "/" + lang
        path = path.replace(prev, next if lang != "en" else "")
    elif lang != "en":
        path = "/" + lang + path
    
    # Final trailing slash check
    if path != '/' and path.endswith('/'):
        path = path.rstrip('/')
    
    # Return path or full URL
    if not full:
        return path
    else:
        # Rebuild full URL preserving query params if needed
        replit_domain = os.environ.get('REPLIT_DEV_DOMAIN')
        if replit_domain:
            base = 'https://' + replit_domain
        else:
            base = request.url_root.rstrip("/")
        result = base + path
        if parsed.query:
            result += "?" + parsed.query
        if parsed.fragment:
            result += "#" + parsed.fragment
        return result


def register_general_routes(app):
    from configs.filetypes import available_filetypes, available_hashtypes
    from configs.definition import definitions
    from configs.languages import supported_languages
    from configs.seo import seo
    from configs.otpages import otpages

    @app.route('/switch-language/<lang>')
    def swith_language(lang):
        if lang in supported_languages.keys():
            g.lang_code = lang

        if request.referrer:
            path = replace_url_lang(request.referrer, lang)
            return redirect(path)
        else:
            return redirect("/")

    @app.route("/<lang_code>/online-convert")
    @app.route("/online-convert")
    def onlineconvert():
        return render_template('otpages.html', filetypes=available_filetypes)

        
    @app.route('/screenshot', methods=['GET'])
    @app.route('/<lang_code>/screenshot', methods=['GET'])
    def screenshot_page():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='screenshot')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template('screenshot.html', page_id=page_id, page_faqs=page_faqs)

    @app.route('/capture-screenshot', methods=['POST'])
    @app.route('/<lang_code>/capture-screenshot', methods=['POST'])
    def capture_screenshot():
        _is_ajax = request.headers.get('X-Requested-With') == 'XMLHttpRequest'

        def _err(msg):
            if _is_ajax:
                return jsonify({'ok': False, 'error': msg})
            flash(msg, 'error')
            return redirect(url_for('screenshot_page'))

        _uid = session.get('user_id')
        _ip  = get_client_ip()
        _lim = check_conversion_limit(user_id=_uid, ip_address=_ip, tool_type='screenshot')
        if not _lim['allowed']:
            return _err(
                f"You have reached your daily screenshot limit ({_lim['limit']}) "
                f"on the {_lim['plan_name']} plan. Upgrade to capture more."
            )

        target_url = request.form.get('url', '').strip()
        if not target_url:
            return _err('Please enter a URL.')

        if not target_url.startswith(('http://', 'https://')):
            return _err('URL must start with http:// or https://')

        width = int(request.form.get('width', 1280))
        height = int(request.form.get('height', 1280))
        zoom = int(request.form.get('zoom', 100))
        fullsize_val = request.form.get('fullsize', 'false')
        fullsize = fullsize_val.lower() in ('true', '1', 'yes', 'on')
        fmt = request.form.get('format', 'png').lower().strip()
        scale = int(request.form.get('scale', 100))

        width = max(320, min(3840, width))
        height = max(200, min(10000, height))
        zoom = max(25, min(500, zoom))
        scale = max(10, min(200, scale))

        if fmt not in FORMAT_EXT:
            fmt = 'png'
        ext = FORMAT_EXT[fmt]

        driver = None
        try:
            initial_height = 800 if fullsize else height
            driver = create_driver(width, initial_height, zoom)

            img = capture_screenshot_image(driver, target_url, width, height, fullsize, zoom)

            img = apply_scale(img, scale)

            filename = f'screenshot_{uuid.uuid4().hex[:12]}.{ext}'
            filepath = os.path.join(SCREENSHOT_DIR, filename)

            save_in_format(img, filepath, fmt)

            record_tool_usage('screenshot', user_id=_uid, ip_address=_ip, file_name=filename)
            if _is_ajax:
                return jsonify({'ok': True, 'redirect': url_for('result_page', filename=filename)})
            return redirect(url_for('result_page', filename=filename))

        except Exception as e:
            return _err(f'Screenshot capture failed: {str(e)}')

        finally:
            if driver:
                try:
                    driver.quit()
                except Exception:
                    pass

    @app.route('/result/<filename>', methods=['GET'])
    @app.route('/<lang_code>/result/<filename>', methods=['GET'])
    def result_page(filename):
        screenshot_path = url_for('static', filename=f'screenshots/{filename}')
        return render_template('result.html', screenshot_path=screenshot_path)
       
    @app.route('/image-bg-remove', methods=['GET'])   
    @app.route('/<lang_code>/image-bg-remove', methods=['GET'])
    def image_bg_remove_page():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='image-bg-remove')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template('image-bg-remove.html', page_id=page_id, page_faqs=page_faqs)

    @app.route('/image-bg-remove/process', methods=['POST'])
    @app.route('/<lang_code>/image-bg-remove/process', methods=['POST'])
    def image_bg_remove_process():
        _uid = session.get('user_id')
        _ip  = get_client_ip()
        _lim = check_conversion_limit(user_id=_uid, ip_address=_ip, tool_type='bg_remove')
        if not _lim['allowed']:
            return jsonify({
                'ok': False,
                'limit_exceeded': True,
                'error': (
                    f"You have reached your daily background-removal limit ({_lim['limit']}) "
                    f"on the {_lim['plan_name']} plan. Upgrade to remove more backgrounds."
                ),
                'used': _lim['used'],
                'limit': _lim['limit'],
                'upgrade_url': '/pricing',
            }), 429

        file = request.files.get('image')
        error = validate_image(file)
        if error:
            return jsonify({'ok': False, 'error': error}), 400

        try:
            result = remove_background(file)
            record_tool_usage('bg_remove', user_id=_uid, ip_address=_ip,
                              file_name=file.filename or 'image')
            return jsonify({
                'ok': True,
                'original_url': result['original_url'],
                'result_url': result['result_url'],
            })
        except Exception as e:
            import logging
            logging.getLogger(__name__).exception("Background removal failed")
            return jsonify({'ok': False, 'error': 'Processing failed. Please try a different image.'}), 500
    


    @app.route('/favico.ico')
    @app.route('/favicon.ico')
    def favicon():
        return send_from_directory(os.path.join(app.root_path, 'static'),
                                   'favico.ico',
                                   mimetype='image/vnd.microsoft.icon')

    @app.route('/onlineconvert-favico.ico')
    @app.route('/onlineconvert-favicon.ico')
    def favicon2():
        return send_from_directory(os.path.join(app.root_path, 'static'),
                                   'onlineconvert-favicon.ico',
                                   mimetype='image/vnd.microsoft.icon')

    @app.route('/ads.txt')
    def adstxt():
        return send_from_directory(os.path.join(app.root_path, 'static'),
                                   'ads.txt',
                                   mimetype='text/plain')

    @app.route('/robots.txt')
    def robotstxt():
        return send_from_directory(os.path.join(app.root_path, 'static'),
                                   'robots.txt',
                                   mimetype='text/plain')

    @app.route("/<lang_code>/formats")
    @app.route('/formats')
    def formats():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='formats')
        page_faqs = get_page_faqs(page_id, lang)
        types = {}
        q = request.args.get("q")
        if q == None:
            q = ""

        for filetype in available_filetypes:
            for ext in available_filetypes[filetype]['ext']:
                if q != None and \
                    (
                        q.lower() in ext.lower() or
                        q.lower() in definitions[ext]
                    ):
                    types[ext] = {"type": filetype, "def": definitions[ext]}
                elif (q == None):
                    types[ext] = {"type": filetype, "def": definitions[ext]}
        return render_template('formats.html', types=types, q=q, page_id=page_id, page_faqs=page_faqs)

      


    @app.route("/<lang_code>/download/<path:filepath>")
    @app.route('/download/<path:filepath>')
    def download_file(filepath):
        try:
            directory = os.path.join(app.config['UPLOAD_DIR'])
            return send_from_directory(
                directory,
                filepath,
                as_attachment=True
            )
        except:
            abort(404)



    

    @app.route("/<lang_code>/blogs")
    @app.route('/blogs')
    def blogs():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='blogs')
        page_faqs = get_page_faqs(page_id, lang)
        blogs_list = []
        with sqlite3.connect("storage/sqlite.db") as connection:
            connection.row_factory = sqlite3.Row
            cursor = connection.cursor()
            cursor.execute("""
                SELECT b.rowid, b.*, u.username as author_name
                FROM blogs b
                LEFT JOIN users u ON u.id = b.author_user_id
                WHERE b.status = 'published'
                ORDER BY b.rowid DESC
            """)
            blogs_list = cursor.fetchall()
            cursor.close()
        return render_template("blogs.html", blogs=blogs_list, page_id=page_id, page_faqs=page_faqs)

    @app.route("/<lang_code>/blogs/<slug>")
    @app.route('/blogs/<slug>')
    def blog(slug):
        slug_lower = slug.lower()

        with sqlite3.connect("storage/sqlite.db") as connection:
            cursor = connection.cursor()

            cursor.execute("SELECT rowid, * FROM blogs WHERE LOWER(slug) = ?",
                           (slug_lower, ))
            blog_post = cursor.fetchone()

            cursor.close()

        if blog_post is None:
            return redirect('/blogs')

        return render_template("blog.html", blog=blog_post)

    @app.route("/<lang_code>/disclaimer")
    @app.route('/disclaimer')
    def disclaimer():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='disclaimer')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template("disclaimer.html", page_id=page_id, page_faqs=page_faqs)

    @app.route("/<lang_code>/report", methods=['GET', 'POST'])
    @app.route('/report', methods=['GET', 'POST'])
    def report():
        sitekey = "6LfbfIYlAAAAAN9SKS8JffEtG6UKFgb0nmYHa1Pd"
        success_message = None
        if request.method == 'POST':
            contact_type = 'issue'
            name = request.form['name']
            email = request.form['email']
            message = request.form['message']
            captcha_response = request.form['g-recaptcha-response']

            if is_human(captcha_response):

                conn = sqlite3.connect('storage/sqlite.db')
                c = conn.cursor()
                c.execute(
                    "INSERT INTO messages (contact_type, name, email, message) VALUES (?, ?, ?, ?)",
                    (contact_type, name, email, message))
                conn.commit()
                conn.close()

                return render_template('report.html', success_message=True)
            else:

                return render_template('report.html',
                                       captcha=True,
                                       sitekey=sitekey)
        else:

            return render_template('report.html',
                                   success_message=success_message,
                                   sitekey=sitekey)

    @app.route("/<lang_code>/privacy")
    @app.route('/privacy')
    def privacy():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='privacy')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template("privacy.html", page_id=page_id, page_faqs=page_faqs)

    @app.route("/<lang_code>/terms")
    @app.route('/terms')
    def terms():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='terms')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template("terms.html", page_id=page_id, page_faqs=page_faqs)

    @app.route("/<lang_code>/imprint")
    @app.route('/imprint')
    def imprint():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='imprint')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template("imprint.html", page_id=page_id, page_faqs=page_faqs)

    @app.route("/<lang_code>/about")
    @app.route('/about')
    def about():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='about')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template("about.html", page_id=page_id, page_faqs=page_faqs)

    @app.route("/<lang_code>/faq")
    @app.route('/faq')
    def faq():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='faq')
        page_faqs = get_page_faqs(page_id, lang)
        return render_template("faq.html", page_id=page_id, page_faqs=page_faqs)
    
    @app.route('/auth/google-one-tap', methods=['POST', 'OPTIONS'])
    def auth_google_one_tap():
        """Handle Google One Tap sign-in without google-auth library"""

        # Handle OPTIONS preflight request for CORS
        if request.method == 'OPTIONS':
            response = make_response()
            origin = request.headers.get('Origin')
            if origin and (origin == f"https://{website_url}" or origin.endswith(f".{website_url}")):
                response.headers['Access-Control-Allow-Origin'] = origin
                response.headers['Access-Control-Allow-Credentials'] = 'true'
                response.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS'
                response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
            return response

        try:
            data = request.get_json()
            credential = data.get('credential')

            if not credential:
                return jsonify({'success': False, 'error': 'No credential provided'}), 400

            # Import ALL needed functions from helpers
            from helpers import get_site_settings, get_user_by_email, get_user_by_username, log_event

            # Get your Google client ID from settings
            site_settings = get_site_settings()
            client_id = site_settings.get('google_client_id')

            if not client_id:
                return jsonify({'success': False, 'error': 'Google login not configured'}), 400

            # Verify the token manually using Google's token info endpoint
            import requests as http_requests

            # Google's token verification endpoint
            token_info_url = f"https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={credential}"

            response = http_requests.get(token_info_url)

            if response.status_code != 200:
                return jsonify({'success': False, 'error': 'Invalid token'}), 400

            id_info = response.json()

            # Verify the audience (client ID) matches
            if id_info.get('aud') != client_id:
                return jsonify({'success': False, 'error': 'Token audience mismatch'}), 400

            # Check if email is verified
            if not id_info.get('email_verified'):
                return jsonify({'success': False, 'error': 'Email not verified by Google'}), 400

            # Get user info from the token
            google_user_id = id_info['sub']
            email = id_info['email']
            name = id_info.get('name', '')
            picture = id_info.get('picture', '')

            # Check if user exists by email
            user = get_user_by_email(email)

            if not user:
                # Create new user
                import secrets
                import hashlib

                # Generate username from email
                username = email.split('@')[0]
                # Make sure username is unique
                base_username = username
                counter = 1
                while get_user_by_username(username):
                    username = f"{base_username}{counter}"
                    counter += 1

                # Generate a random password (user will never use it)
                random_password = secrets.token_urlsafe(32)
                password_hash = hashlib.sha256(random_password.encode()).hexdigest()

                with sqlite3.connect("storage/sqlite.db") as conn:
                    cursor = conn.execute('''
                        INSERT INTO users (
                            username, email, password_hash, google_id, 
                            display_name, profile_picture, email_verified, 
                            plan_id, created_at
                        ) VALUES (?, ?, ?, ?, ?, ?, 1, 1, datetime('now'))
                    ''', (username, email, password_hash, google_user_id, name, picture))

                    user_id = cursor.lastrowid
                    conn.commit()

                # Log the registration
                log_event('user_registered', f"New user registered via Google: {username} ({email})", user_id=user_id, username=username)

            else:
                user_id = user['id']
                # Update Google ID if not set
                if not user.get('google_id'):
                    with sqlite3.connect("storage/sqlite.db") as conn:
                        conn.execute(
                            'UPDATE users SET google_id = ? WHERE id = ?',
                            (google_user_id, user_id)
                        )
                        conn.commit()

            # Log the user in
            session['user_id'] = user_id
            session.permanent = True
            session.modified = True  # Force session to be saved

            # Log the login event
            log_event('user_login', f"User logged in via Google One Tap", user_id=user_id, username=user.get('username') if user else username)

            current_url = data.get('current_url')

            # Determine where to redirect - priority: referrer > sent URL > fallback
            redirect_url = request.referrer or current_url

            if not redirect_url:
                # Last resort fallback - redirect to home page
                redirect_url = url_for('index', _external=True)

            # Make sure URL uses HTTPS
            if redirect_url.startswith('http://'):
                redirect_url = redirect_url.replace('http://', 'https://', 1)

            # Create response with proper CORS headers
            response = jsonify({
                'success': True, 
                'redirect_url': redirect_url
            })

            # MANUALLY SET THE COOKIE WITH CORRECT DOMAIN
            if session.get('user_id'):
                # Get the session cookie value from Flask's session object
                # We need to save the session first
                from flask import session as flask_session
                flask_session.modified = True
                
                # Get the session cookie name from app config
                cookie_name = app.config.get('SESSION_COOKIE_NAME', 'session')
                
                # Get the session data as a string (Flask handles this internally)
                # Instead of trying to get the cookie value, we let Flask set it
                # but we override the domain
                response.set_cookie(
                    cookie_name,
                    value=request.cookies.get(cookie_name, ''),  # This might not work
                    domain='.' + website_url,  # Force the dot prefix
                    secure=app.config.get('SESSION_COOKIE_SECURE', True),
                    httponly=app.config.get('SESSION_COOKIE_HTTPONLY', True),
                    samesite=app.config.get('SESSION_COOKIE_SAMESITE', 'Lax'),
                    path='/'
                )

            # Add CORS headers to response
            origin = request.headers.get('Origin')
            if origin and (origin == f"https://{website_url}" or origin.endswith(f".{website_url}")):
                response.headers['Access-Control-Allow-Origin'] = origin
                response.headers['Access-Control-Allow-Credentials'] = 'true'

            return response

        except Exception as e:
            app.logger.error(f"Google One Tap error: {e}")

            # Create error response with CORS headers
            response = jsonify({'success': False, 'error': str(e)})
            origin = request.headers.get('Origin')
            if origin and (origin == f"https://{website_url}" or origin.endswith(f".{website_url}")):
                response.headers['Access-Control-Allow-Origin'] = origin
                response.headers['Access-Control-Allow-Credentials'] = 'true'

            return response, 500
            
            
    @app.route('/api/drive-file', methods=['POST'])
    def get_drive_file():
        """Handle Google Drive file selection and return download info"""
        try:
            data = request.get_json()
            file_id = data.get('fileId')
            access_token = data.get('accessToken')

            if not file_id or not access_token:
                return jsonify({'error': 'Missing file ID or access token'}), 400

            # Use the access token to get file metadata
            import requests

            # Get file metadata to know the filename
            metadata_url = f'https://www.googleapis.com/drive/v3/files/{file_id}?fields=name,mimeType,size'
            headers = {'Authorization': f'Bearer {access_token}'}

            meta_response = requests.get(metadata_url, headers=headers)

            if meta_response.status_code != 200:
                return jsonify({'error': 'Failed to get file metadata'}), 400

            file_info = meta_response.json()

            # Generate a download URL that works with your existing system
            # We'll use a signed URL approach or proxy the download

            # For now, return the file info and let frontend handle download
            return jsonify({
                'success': True,
                'fileId': file_id,
                'fileName': file_info.get('name', 'unknown'),
                'mimeType': file_info.get('mimeType', ''),
                'size': file_info.get('size', 0),
                'accessToken': access_token  # Send back for download
            })

        except Exception as e:
            app.logger.error(f"Drive file error: {e}")
            return jsonify({'error': str(e)}), 500


    @app.route('/api/drive-download', methods=['GET'])
    def drive_download():
        """Proxy for downloading Google Drive files (including Google Workspace exports)"""
        file_id = request.args.get('id')
        access_token = request.args.get('token')
        filename = request.args.get('filename', 'file.bin')
        mime_type = request.args.get('mime', '')

        if not file_id or not access_token:
            return jsonify({'error': 'Missing parameters'}), 400

        auth_headers = {'Authorization': f'Bearer {access_token}'}

        # Google Workspace files cannot be downloaded directly — use the export API
        _workspace_export_map = {
            'application/vnd.google-apps.document':     ('application/vnd.openxmlformats-officedocument.wordprocessingml.document', '.docx'),
            'application/vnd.google-apps.spreadsheet':  ('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', '.xlsx'),
            'application/vnd.google-apps.presentation': ('application/vnd.openxmlformats-officedocument.presentationml.presentation', '.pptx'),
            'application/vnd.google-apps.drawing':      ('image/png', '.png'),
            'application/vnd.google-apps.script':       ('application/vnd.google-apps.script+json', '.json'),
            'application/vnd.google-apps.form':         ('application/pdf', '.pdf'),
        }

        if mime_type in _workspace_export_map:
            export_mime, ext = _workspace_export_map[mime_type]
            # Append correct extension if missing
            if not filename.lower().endswith(ext):
                filename = filename + ext
            download_url = f'https://www.googleapis.com/drive/v3/files/{file_id}/export?mimeType={export_mime}'
        else:
            # Regular binary file
            download_url = f'https://www.googleapis.com/drive/v3/files/{file_id}?alt=media'

        resp = requests.get(download_url, headers=auth_headers, stream=True)

        if resp.status_code != 200:
            # Try fetching metadata to give a better error
            try:
                err_body = resp.json()
                err_msg = err_body.get('error', {}).get('message', f'HTTP {resp.status_code}')
            except Exception:
                err_msg = f'HTTP {resp.status_code}'
            return jsonify({'error': f'Failed to download file: {err_msg}'}), 400

        response = make_response()
        response.data = resp.content
        content_type = resp.headers.get('Content-Type', 'application/octet-stream').split(';')[0].strip()
        response.headers['Content-Type'] = content_type
        response.headers['Content-Disposition'] = f'attachment; filename="{filename}"'
        return response
            

    
    @app.route("/<lang_code>/contact", methods=['GET', 'POST'])
    @app.route('/contact', methods=['GET', 'POST'])
    def contact():
        lang = getattr(g, 'lang_code', 'en')
        page_id = normalize_page_id(static_page='contact')
        page_faqs = get_page_faqs(page_id, lang)
        sitekey = "6LfbfIYlAAAAAN9SKS8JffEtG6UKFgb0nmYHa1Pd"
        success_message = None
        if request.method == 'POST':
            contact_type = request.form['contact_type']
            name = request.form['name']
            email = request.form['email']
            message = request.form['message']
            captcha_response = request.form['g-recaptcha-response']

            if is_human(captcha_response):

                conn = sqlite3.connect('storage/sqlite.db')
                c = conn.cursor()
                c.execute(
                    "INSERT INTO messages (contact_type, name, email, message) VALUES (?, ?, ?, ?)",
                    (contact_type, name, email, message))
                conn.commit()
                conn.close()

                return render_template('contact.html', success_message=True,
                                       page_id=page_id, page_faqs=page_faqs)
            else:

                return render_template('contact.html',
                                       captcha=True,
                                       sitekey=sitekey,
                                       page_id=page_id, page_faqs=page_faqs)
        else:

            return render_template('contact.html',
                                   success_message=success_message,
                                   sitekey=sitekey,
                                   page_id=page_id, page_faqs=page_faqs)

    # ── Broadcast analytics tracking endpoints ───────────────────────────────
    # Token format: "<user_id_hex>.<hmac8>" — user_id embedded in token itself
    # so URL is /t/eo/<broadcast_id>/<token> (no bare user_id in path).

    def _tracking_secret():
        # 1. Explicit SECRET_KEY env var
        s = os.getenv('SECRET_KEY', '').strip()
        if s:
            return s
        # 2. Admin-panel setting: Admin → General Settings → Broadcast Secret Key
        try:
            from helpers import get_site_settings as _gss
            s = (_gss().get('broadcast_secret_key') or '').strip()
            if s:
                return s
        except Exception:
            pass
        # 3. Fall back to the Flask session secret (always configured)
        try:
            from flask import current_app
            s = current_app.secret_key or ''
            if isinstance(s, bytes):
                s = s.decode('utf-8', errors='replace')
            if s:
                return s
        except Exception:
            pass
        raise RuntimeError("Set a Broadcast Secret Key in Admin → General Settings → Broadcast")

    def _make_tracking_token(broadcast_id, user_id):
        """Token = '<user_id_hex>.<8-char HMAC>' — user identity + integrity check."""
        import hmac, hashlib
        uid_hex = format(user_id, 'x')
        msg = f"{broadcast_id}:{user_id}".encode()
        sig = hmac.new(_tracking_secret().encode(), msg, hashlib.sha256).hexdigest()[:8]
        return f"{uid_hex}.{sig}"

    def _verify_tracking_token(broadcast_id, token):
        """Parse token, extract user_id, verify HMAC. Returns user_id or None."""
        import hmac
        try:
            uid_hex, sig = token.split('.', 1)
            user_id = int(uid_hex, 16)
        except Exception:
            return None
        expected = _make_tracking_token(broadcast_id, user_id)
        if hmac.compare_digest(expected, token):
            return user_id
        return None

    @app.route('/t/eo/<int:broadcast_id>/<token>')
    def track_email_open(broadcast_id, token):
        """Tracking pixel endpoint — increments email_open_count."""
        user_id = _verify_tracking_token(broadcast_id, token)
        if user_id is not None:
            try:
                with _db() as c:
                    c.execute(
                        """UPDATE broadcast_recipients
                           SET email_open_count = email_open_count + 1,
                               email_opened_at = COALESCE(email_opened_at, datetime('now'))
                           WHERE broadcast_id=? AND user_id=?""",
                        (broadcast_id, user_id)
                    )
                    c.commit()
            except Exception:
                pass
        # Return a 1×1 transparent GIF with no-cache headers
        gif = (b'GIF89a\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00'
               b'!\xf9\x04\x00\x00\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01'
               b'\x00\x00\x02\x02D\x01\x00;')
        resp = make_response(gif)
        resp.headers['Content-Type'] = 'image/gif'
        resp.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
        resp.headers['Pragma'] = 'no-cache'
        resp.headers['Expires'] = '0'
        return resp

    @app.route('/t/pc/<int:broadcast_id>/<token>')
    def track_push_click(broadcast_id, token):
        """Push-click beacon endpoint — increments push_click_count."""
        user_id = _verify_tracking_token(broadcast_id, token)
        if user_id is not None:
            try:
                with _db() as c:
                    c.execute(
                        """UPDATE broadcast_recipients
                           SET push_click_count = push_click_count + 1,
                               push_clicked_at = COALESCE(push_clicked_at, datetime('now'))
                           WHERE broadcast_id=? AND user_id=?""",
                        (broadcast_id, user_id)
                    )
                    c.commit()
            except Exception:
                pass
        return '', 204

    @app.errorhandler(404)
    def page_not_found(e):
        return render_template("404.html"), 404

    @app.errorhandler(500)
    def internal_error(error):
        app.logger.error(f"Internal Server Error: {error}")
        return render_template("404.html"), 500
