# app/__init__.py

from flask import Flask, render_template, request, session
from flask_login import login_user, logout_user, login_required, current_user
from flask_wtf.csrf import CSRFProtect
from config import Config
from app.extensions import db, login_manager, migrate, csrf
import os
from datetime import datetime, timedelta
import logging
import locale
from app.helpers import get_role_persian
from app.filters import max_value, clamp, percentage
from app.context_processors import (
    utility_processor,
    employer_context,
    manager_context,
    employee_context
)

from datetime import datetime, timedelta
from app.filters import register_filters

# تنظیم لاگر
logger = logging.getLogger(__name__)


def create_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(config_class)
    
    # ============================================
    # ✅ تنظیمات Session
    # ============================================
    app.config['SESSION_COOKIE_HTTPONLY'] = True
    app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
    app.config['SESSION_COOKIE_SECURE'] = False
    app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=1)
    app.config['REMEMBER_COOKIE_DURATION'] = timedelta(days=30)
    app.config['REMEMBER_COOKIE_HTTPONLY'] = True
    app.config['REMEMBER_COOKIE_SAMESITE'] = 'Lax'
    
    # ============================================
    # ✅ ایجاد دایرکتوری‌ها
    # ============================================
    upload_folder = app.config.get('UPLOAD_FOLDER', 'static/uploads')
    upload_ads_folder = app.config.get('UPLOAD_FOLDER_ADS', 'static/uploads/advertisements')
    
    os.makedirs(upload_folder, exist_ok=True)
    os.makedirs(upload_ads_folder, exist_ok=True)
    
    # ============================================
    # ✅ تنظیمات CSRF
    # ============================================
    app.config['WTF_CSRF_ENABLED'] = True
    app.config['WTF_CSRF_SECRET_KEY'] = app.config['SECRET_KEY']
    app.config['WTF_CSRF_TIME_LIMIT'] = 3600
    
    # ============================================
    # ✅ مقداردهی اولیه extensions
    # ============================================
    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)
    csrf.init_app(app)
    
    # ============================================
    # ✅ تنظیمات Login Manager
    # ============================================
    login_manager.login_view = 'auth.login'
    login_manager.login_message = 'لطفاً برای دسترسی به این صفحه وارد شوید.'
    login_manager.login_message_category = 'info'
    login_manager.session_protection = 'strong'
    
    # ============================================
    # ✅ User Loader
    # ============================================
    @login_manager.user_loader
    def load_user(user_id):
        from app.models import User
        try:
            if isinstance(user_id, str):
                user_id = int(user_id)
            user = User.query.get(user_id)
            return user
        except Exception as e:
            logger.error(f"خطا در بارگذاری کاربر: {e}")
            return None
    
    # ============================================
    # ✅ فیلترهای Jinja2
    # ============================================
    
    @ app.template_filter('add_days')
    def add_days(date, days):
        """افزودن تعداد روز به تاریخ"""
        if not date:
            return date
        try:
            from datetime import timedelta
            if isinstance(date, str):
                from datetime import datetime
                date = datetime.strptime(date, '%Y-%m-%d').date()
            return date + timedelta(days=int(days))
        except Exception as e:
            return date

    @app.template_filter('format_duration')
    def format_duration_filter(value):
        try:
            if not value:
                return '00:00:00'
            total_seconds = int(float(value))
            hours = total_seconds // 3600
            minutes = (total_seconds % 3600) // 60
            secs = total_seconds % 60
            return f'{hours:02d}:{minutes:02d}:{secs:02d}'
        except (ValueError, TypeError):
            return '00:00:00'
    
    @app.template_filter('format_duration_hours')
    def format_duration_hours_filter(value):
        try:
            if not value:
                return '۰ ساعت'
            total_seconds = int(float(value))
            hours = total_seconds // 3600
            minutes = (total_seconds % 3600) // 60
            if hours > 0 and minutes > 0:
                return f'{hours} ساعت و {minutes} دقیقه'
            elif hours > 0:
                return f'{hours} ساعت'
            elif minutes > 0:
                return f'{minutes} دقیقه'
            else:
                return 'کمتر از یک دقیقه'
        except (ValueError, TypeError):
            return '۰ ساعت'
    
    @app.template_filter('format_duration_hours_only')
    def format_duration_hours_only_filter(value):
        try:
            if not value:
                return '۰.۰۰'
            hours = float(value) / 3600
            return f'{hours:.2f}'
        except (ValueError, TypeError):
            return '۰.۰۰'
    
    @app.template_filter('format_number')
    def format_number_filter(value):
        if value is None:
            return '۰'
        try:
            return f"{int(float(value)):,}"
        except (ValueError, TypeError):
            return str(value)
    
    @app.template_filter('persian_number')
    def persian_number_filter(value):
        if value is None:
            return '۰'
        persian_digits = {'0': '۰', '1': '۱', '2': '۲', '3': '۳', '4': '۴', 
                          '5': '۵', '6': '۶', '7': '۷', '8': '۸', '9': '۹'}
        return ''.join(persian_digits.get(c, c) for c in str(value))
    
    @app.template_filter('persian_date')
    def persian_date_filter(date_obj):
        if not date_obj:
            return ''
        try:
            import jdatetime
            return jdatetime.datetime.fromgregorian(datetime=date_obj).strftime('%Y/%m/%d')
        except ImportError:
            return date_obj.strftime('%Y/%m/%d')
    
    @app.template_filter('persian_datetime')
    def persian_datetime_filter(dt):
        if not dt:
            return ''
        try:
            import jdatetime
            return jdatetime.datetime.fromgregorian(datetime=dt).strftime('%Y/%m/%d %H:%M')
        except ImportError:
            return dt.strftime('%Y/%m/%d %H:%M')
    
    @app.template_filter('persian_time')
    def persian_time_filter(dt):
        if not dt:
            return ''
        return dt.strftime('%H:%M')
    
    @app.template_filter('truncate_text')
    def truncate_text_filter(text, length=100, suffix='...'):
        if not text:
            return ''
        if len(text) <= length:
            return text
        return text[:length] + suffix
    
    @app.template_filter('get_status_badge')
    def get_status_badge_filter(status):
        status_map = {
            'pending': 'warning',
            'approved': 'success',
            'paid': 'primary',
            'rejected': 'danger',
            'active': 'success',
            'overdue': 'danger',
            'completed': 'success',
            'cancelled': 'secondary',
            'verified': 'success'
        }
        return status_map.get(status, 'secondary')
    
    @app.template_filter('get_status_text')
    def get_status_text_filter(status):
        status_map = {
            'pending': 'در انتظار',
            'approved': 'تایید شده',
            'paid': 'پرداخت شده',
            'rejected': 'رد شده',
            'active': 'فعال',
            'overdue': 'معوق',
            'completed': 'تکمیل شده',
            'cancelled': 'لغو شده',
            'verified': 'تایید شده'
        }
        return status_map.get(status, status)
    
    # ============================================
    # ✅ ثبت فیلترهای سفارشی
    # ============================================
    app.jinja_env.filters['max_value'] = max_value
    app.jinja_env.filters['clamp'] = clamp
    app.jinja_env.filters['percentage'] = percentage
    
    # ============================================
    # ✅ ثبت Context Processors (به عنوان دیکشنری)
    # ============================================
    
    # 1. Context processor اصلی
    @app.context_processor
    def main_context():
        """Context processor اصلی با توابع کمکی"""
        
        def format_number(value):
            try:
                if value is None:
                    return '۰'
                num = int(float(value))
                return f"{num:,}".replace(',', '٬')
            except (ValueError, TypeError):
                return str(value)
        
        def max_value_func(value, max_val):
            try:
                value = float(value)
                max_val = float(max_val)
                return min(value, max_val)
            except (ValueError, TypeError):
                return value
        
        def clamp_func(value, min_val=None, max_val=None):
            try:
                value = float(value)
                if min_val is not None:
                    value = max(value, float(min_val))
                if max_val is not None:
                    value = min(value, float(max_val))
                return value
            except (ValueError, TypeError):
                return value
        
        return {
            'format_number': format_number,
            'max_value': max_value_func,
            'clamp': clamp_func,
            'now': datetime.now(),
            'current_year': datetime.now().year
        }
    
    # 2. Context processor برای CSRF
    @app.context_processor
    def csrf_context():
        return {
            'csrf_token': lambda: csrf._get_csrf_token(),
            'csrf': csrf
        }
    
    # 3. Context processor برای نوتیفیکیشن
    @app.context_processor
    def notification_context():
        from app.models import Notification
        
        def get_unread_count():
            if current_user.is_authenticated:
                try:
                    return Notification.query.filter_by(
                        user_id=current_user.id, 
                        is_read=False
                    ).count()
                except Exception as e:
                    return 0
            return 0
        
        return {
            'Notification': Notification,
            'get_unread_count': get_unread_count
        }
    
    # ============================================
    # ✅ ثبت Blueprintها
    # ============================================
    from app.dashboard import dashboard_bp
    from app.public import public_bp
    from app.auth import auth_bp
    from app.admin import admin_bp
    from app.manager import manager_bp
    from app.employer import employer_bp
    from app.employee import employee_bp
    
    app.register_blueprint(dashboard_bp)
    app.register_blueprint(public_bp, url_prefix='/public')
    app.register_blueprint(auth_bp, url_prefix='/auth')
    app.register_blueprint(admin_bp, url_prefix='/admin')
    app.register_blueprint(manager_bp, url_prefix='/manager')
    app.register_blueprint(employer_bp, url_prefix='/employer')
    app.register_blueprint(employee_bp, url_prefix='/employee')
    
    #====
    
    register_filters(app)
    
    # ============================================
    # ✅ ایجاد جداول و کاربران پیش‌فرض
    # ============================================
    with app.app_context():
        from app.models import User
        
        try:
            db.create_all()
            logger.info("✅ جداول با موفقیت ایجاد شدند")
        except Exception as e:
            logger.error(f"❌ خطا در ایجاد جداول: {e}")
        
        # ایجاد کاربران پیش‌فرض
        try:
            admin = User.query.filter_by(role='admin').first()
            if not admin:
                admin = User(
                    username='admin',
                    fullname='مدیر سیستم',
                    phone='09123456789',
                    email='admin@example.com',
                    role='admin',
                    is_active=True,
                    is_verified=True,
                    manager_request_status='approved'
                )
                admin.set_password('admin123')
                db.session.add(admin)
                logger.info("✅ کاربر ادمین ایجاد شد: admin / admin123")
            
            manager = User.query.filter_by(username='manager1').first()
            if not manager:
                manager = User(
                    username='manager1',
                    fullname='مدیر پروژه نمونه',
                    phone='09123456788',
                    email='manager@example.com',
                    role='manager',
                    is_active=True,
                    is_verified=True,
                    manager_request_status='approved'
                )
                manager.set_password('manager123')
                db.session.add(manager)
                logger.info("✅ کاربر مدیر پروژه ایجاد شد: manager1 / manager123")
            
            employer = User.query.filter_by(username='employer1').first()
            if not employer:
                employer = User(
                    username='employer1',
                    fullname='کارفرمای نمونه',
                    phone='09123456787',
                    email='employer@example.com',
                    role='employer',
                    is_active=True,
                    is_verified=True,
                    manager_request_status='approved'
                )
                employer.set_password('employer123')
                db.session.add(employer)
                logger.info("✅ کاربر کارفرما ایجاد شد: employer1 / employer123")
            
            employee = User.query.filter_by(username='employee1').first()
            if not employee:
                employee = User(
                    username='employee1',
                    fullname='عامل اجرایی نمونه',
                    phone='09123456786',
                    email='employee@example.com',
                    role='employee',
                    is_active=True,
                    is_verified=True,
                    manager_request_status='approved'
                )
                employee.set_password('employee123')
                db.session.add(employee)
                logger.info("✅ کاربر عامل اجرایی ایجاد شد: employee1 / employee123")
            
            db.session.commit()
            
        except Exception as e:
            db.session.rollback()
            logger.error(f"❌ خطا در ایجاد کاربران پیش‌فرض: {e}")
        
        # نمایش خلاصه کاربران
        print("\n" + "="*60)
        print("📊 خلاصه کاربران سیستم:")
        print("="*60)
        
        all_users = User.query.all()
        if all_users:
            for u in all_users:
                role_persian = get_role_persian(u.role)
                status = "✅ فعال" if u.is_active else "❌ غیرفعال"
                print(f"   {u.username} - {role_persian} - {status}")
        
        print("\n" + "="*60)
        print("🔑 اطلاعات ورود:")
        print("="*60)
        print("   ادمین:        admin / admin123")
        print("   مدیر پروژه:   manager1 / manager123")
        print("   کارفرما:      employer1 / employer123")
        print("   عامل اجرایی:  employee1 / employee123")
        print("="*60)
    
    # ============================================
    # ✅ هندلرهای خطا
    # ============================================
    @app.errorhandler(404)
    def not_found_error(error):
        return render_template('public/404.html'), 404
    
    @app.errorhandler(500)
    def internal_error(error):
        db.session.rollback()
        logger.error(f"خطای 500: {error}")
        return render_template('public/500.html'), 500
    
    @app.errorhandler(403)
    def forbidden_error(error):
        return render_template('public/403.html'), 403
    
    @app.errorhandler(405)
    def method_not_allowed_error(error):
        return render_template('public/405.html'), 405
    
    return app