from flask import Blueprint, render_template, request, redirect, url_for, jsonify
from flask_login import login_required, current_user
from app import db
from sqlalchemy import or_
from plugins.plant.models import Plant, PlantCommonName, PlantScientificName, Tag
from flask_wtf import FlaskForm
from wtforms import StringField, SelectMultipleField, SubmitField
from wtforms.validators import Optional, Length, Regexp

bp = Blueprint(
    'search',
    __name__,
    url_prefix='/search',
    template_folder='templates/search'
)

class SearchForm(FlaskForm):
    query = StringField(
        'Search',
        validators=[
            Optional(),
            Length(min=2, max=100, message="Search term must be between 2 and 100 characters."),
            Regexp(r'^[\w\s\-]+$', message="Search can only include letters, numbers, spaces, and dashes.")
        ]
    )
    tags = SelectMultipleField('Tags', coerce=int)
    submit = SubmitField('Search')

@bp.route('', methods=['GET', 'POST'])
@bp.route('/', methods=['GET', 'POST'])
@login_required
def search():
    form = SearchForm()
    form.tags.choices = [(t.id, t.name) for t in Tag.query.order_by(Tag.name).all()]
    if form.validate_on_submit():
        q = form.query.data or ''
        selected = form.tags.data or []
        tags_param = ','.join(map(str, selected)) if selected else ''
        return redirect(url_for('search.results', q=q, tags=tags_param))
    return render_template('search/search.html', form=form)

@bp.route('/results', methods=['GET'])
@login_required
def results():
    q = request.args.get('q', '').strip()
    tags_param = request.args.get('tags', '')
    tags = [int(t) for t in tags_param.split(',') if t] if tags_param else []
    like_term = f"%{q}%"

    # Base query, joining name tables for text search
    query = (
        db.session.query(Plant)
        .join(Plant.common_name)
        .join(Plant.scientific_name)
    )

    if q:
        query = query.filter(
            or_(
                PlantCommonName.name.ilike(like_term),
                PlantScientificName.name.ilike(like_term),
                Plant.plant_type.ilike(like_term),
            )
        )

    if tags:
        query = query.filter(Plant.tags.any(Tag.id.in_(tags)))

    # Only include active plants…
    query = query.filter(Plant.is_active.is_(True))

    # …and either public plants or those owned by the current user
    query = query.filter(
        or_(
            Plant.is_public.is_(True),
            Plant.owner_id == current_user.id
        )
    )

    results = query.all()
    return render_template(
        'search/results.html',
        results=results,
        query=q,
        tags=tags
    )

@bp.route('/tags')
@login_required
def search_tags():
    term = request.args.get('term', '')
    like_term = f"%{term}%"
    matches = Tag.query.filter(Tag.name.ilike(like_term)).limit(10).all()
    return jsonify([t.name for t in matches])
