from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, TextAreaField, PasswordField, IntegerField, FloatField, SubmitField, BooleanField, SelectField, FieldList, FormField
from wtforms.validators import DataRequired, NumberRange, Optional, Length, ValidationError
from app.models import VehicleCategory, TourParentCategory, TourSubCategory, TourDay
import re
import logging


logger = logging.getLogger(__name__)

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Log In')

class CarForm(FlaskForm):
    name = StringField('Car Name', validators=[DataRequired()])
    capacity = IntegerField('Capacity', validators=[DataRequired(), NumberRange(min=1)])
    price_per_day = FloatField('Price per Day', validators=[DataRequired(), NumberRange(min=0)])
    image = FileField('Image', validators=[FileAllowed(['jpg', 'png', 'jpeg', 'avif', 'webp'], 'Images only!')])
    category = SelectField('Category', choices=[(cat.name, cat.value) for cat in VehicleCategory], validators=[DataRequired()])
    has_ac = BooleanField('Air Conditioning')
    has_usb = BooleanField('USB Ports')
    has_player = BooleanField('Music Player')
    has_bluetooth = BooleanField('Bluetooth')
    luggage_space = StringField('Luggage Space')
    submit = SubmitField('Submit Car')

class TourDayForm(FlaskForm):
    title = StringField('Day Title', validators=[Optional()])
    description = TextAreaField('Day Description', validators=[Optional()])

class TourForm(FlaskForm):
    title = StringField('Tour Title', validators=[DataRequired()])
    subtitle = StringField('Tour Subtitle', validators=[Optional()])
    description = TextAreaField('Description', validators=[Optional()])
    itinerary = TextAreaField('Itinerary', validators=[DataRequired()])
    inclusions = TextAreaField('Inclusions', validators=[Optional()])
    exclusions = TextAreaField('Exclusions', validators=[Optional()])
    additional_info = TextAreaField('Additional Information', validators=[Optional()])
    image = FileField('Tour Image', validators=[FileAllowed(['jpg', 'png', 'jpeg', 'avif', 'webp'], 'Images only!')])
    parent_category = SelectField('Tour Parent Category', coerce=int, validators=[DataRequired()])
    subcategory = SelectField('Tour Subcategory', coerce=int, validators=[DataRequired()])
    duration = StringField('Duration', validators=[DataRequired(), Length(max=50)])
    tour_days = FieldList(FormField(TourDayForm), min_entries=1)
    submit_button = SubmitField('Submit Tour') 

    def __init__(self, *args, **kwargs):
        super(TourForm, self).__init__(*args, **kwargs)
        self.parent_category.choices = [(c.id, c.name) for c in TourParentCategory.query.order_by('name')]
        self.subcategory.choices = [(c.id, f"{c.parent_category.name} - {c.name}") for c in TourSubCategory.query.join(TourParentCategory).order_by(TourParentCategory.name, TourSubCategory.name)]

    def populate_obj(self, obj):
        logger.info(f"Starting to populate Tour object: {obj}")
        for name, field in self._fields.items():
            if name not in ['parent_category', 'subcategory', 'tour_days', 'submit_button', 'image']:
                try:
                    logger.debug(f"Populating field: {name}")
                    if isinstance(field.data, str):
                        setattr(obj, name, field.data)
                    else:
                        field.populate_obj(obj, name)
                except AttributeError as e:
                    logger.error(f"Error populating field {name}: {str(e)}")
                    logger.error(f"Field type: {type(field)}, Field data type: {type(field.data)}")
        
        # Handle subcategory separately
        if self.subcategory.data:
            logger.debug(f"Setting subcategory_id to: {self.subcategory.data}")
            obj.subcategory_id = self.subcategory.data
        
        # Handle tour_days
        logger.info("Populating tour_days")
        obj.tour_days = []
        for i, day_form in enumerate(self.tour_days):
            try:
                title = day_form.form.title.data
                description = day_form.form.description.data
                if title or description:  # Only add the tour day if either title or description is not empty
                    tour_day = TourDay(
                        day_number=i+1,
                        title=title or "Untitled",  # Provide a default title if it's empty
                        description=description or "No description provided"  # Provide a default description if it's empty
                    )
                    obj.tour_days.append(tour_day)
                    logger.debug(f"Added tour day: {tour_day}")
                else:
                    logger.warning(f"Skipped empty tour day at index {i}")
            except AttributeError as e:
                logger.error(f"Error creating tour day {i+1}: {str(e)}")
                logger.error(f"Day form data: {day_form.data}")

        logger.info("Finished populating Tour object")

    def validate_subcategory(self, field):
        parent_category_id = self.parent_category.data
        subcategory = TourSubCategory.query.get(field.data)
        if subcategory and subcategory.parent_category_id != parent_category_id:
            raise ValidationError('Selected subcategory does not belong to the selected parent category.')
        
        
class TourParentCategoryForm(FlaskForm):
    name = StringField('Category Name', validators=[DataRequired(), Length(max=100)])
    display_in_menu = BooleanField('Display in Menu')
    submit = SubmitField('Submit Parent Category')

class TourSubCategoryForm(FlaskForm):
    name = StringField('Subcategory Name', validators=[DataRequired(), Length(max=100)])
    parent_category = SelectField('Parent Category', coerce=int, validators=[DataRequired()])
    image = FileField('Image', validators=[
        FileAllowed(['jpg', 'png', 'jpeg', 'avif', 'webp'], 'Images only! Allowed formats: JPG, PNG, JPEG, AVIF, WebP')
    ])
    submit = SubmitField('Submit Subcategory')

    def __init__(self, *args, **kwargs):
        super(TourSubCategoryForm, self).__init__(*args, **kwargs)
        self.parent_category.choices = [(c.id, c.name) for c in TourParentCategory.query.order_by('name')]

class BlogForm(FlaskForm):
    title = StringField('Title', validators=[DataRequired(), Length(max=200)])
    content = TextAreaField('Content', validators=[DataRequired()])
    feature_image = FileField('Feature Image', validators=[FileAllowed(['jpg', 'png', 'jpeg', 'gif', 'avif', 'webp'], 'Images only!')])
    gallery_image_1 = FileField('Gallery Image 1', validators=[FileAllowed(['jpg', 'png', 'jpeg', 'gif', 'avif', 'webp'], 'Images only!')])
    gallery_image_2 = FileField('Gallery Image 2', validators=[FileAllowed(['jpg', 'png', 'jpeg', 'gif', 'avif', 'webp'], 'Images only!')])
    gallery_image_3 = FileField('Gallery Image 3', validators=[FileAllowed(['jpg', 'png', 'jpeg', 'gif', 'avif', 'webp'], 'Images only!')])
    meta_description = StringField('Meta Description', validators=[Length(max=160)])
    meta_keywords = StringField('Meta Keywords', validators=[Length(max=200)])
    submit = SubmitField('Submit Blog Post')