"""
ABESEKARA POS - MAIN APPLICATION FILE
✅ WITH REFRESH TOKEN SUPPORT
"""

from flask import Flask, jsonify, send_from_directory, request
from flask_cors import CORS
from datetime import timedelta
from werkzeug.security import generate_password_hash, check_password_hash
from flask_jwt_extended import (
    JWTManager, create_access_token, create_refresh_token,
    jwt_required, get_jwt_identity, get_jwt, verify_jwt_in_request
)
from functools import wraps
import os
import secrets
from flask_mail import Mail

# Import Blueprints
from api.login import login_bp
from api.product import product_bp
from api.supplier import supplier_bp
from api.grn import grn_bp
from api.prescription import prescription_bp
from api.purchase import purchase_bp
from api.purchase_return import purchase_return_bp
from api.user import user_bp
from api.sale import sale_bp
from api.sale_return import sale_return_bp
from api.customer import customer_bp
from api.expense import expenses_bp
from api.report import report_bp
from api.patient_history import patient_history_bp
from api.variation import variation_bp
from api.warehouse import warehouse_bp
from api.stores import stores_bp
from api.payment_methods import payment_methods_bp
from api.adjustment import adjustment_bp
from api.quotation import quotation_bp
from api.barcode import barcode_bp
from api.cashier import cashier_bp
from api.stock_tranfer import stock_transfer_bp
from api.doctor import doctor_bp
from api.appoinment import appoinment_bp
from api.session import session_bp
from api.charge import charge_bp
from api.lab_bill import lab_bill_bp




app = Flask(__name__)

# CORS Configuration
FRONTEND_URL = os.getenv("FRONTEND_URL", "http://127.0.0.1:5505")
CORS(app, origins=[FRONTEND_URL], supports_credentials=True)

# File Upload Configuration
UPLOAD_FOLDER = os.path.join(app.root_path, 'static', 'uploads')
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

PRODUCTS_UPLOAD_FOLDER = 'uploads/products'
os.makedirs(PRODUCTS_UPLOAD_FOLDER, exist_ok=True)

app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB

# Mail Configuration
app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = 'realmaxpvtltd@gmail.com'
app.config['MAIL_PASSWORD'] = ''

mail = Mail(app)

# ============================================
# ✅ JWT CONFIGURATION WITH REFRESH TOKENS
# ============================================
JWT_FALLBACK_KEY = 'pos-system-jwt-secret-key-change-in-production'
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY', JWT_FALLBACK_KEY)

# Access token expires in 1 hour
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(hours=1)

# Refresh token expires in 24 hours (user stays logged in for 24 hours)
app.config['JWT_REFRESH_TOKEN_EXPIRES'] = timedelta(days=1)

jwt = JWTManager(app)

# JWT Error Handlers
@jwt.expired_token_loader
def expired_token_callback(jwt_header, jwt_payload):
    return jsonify({'message': 'Token has expired', 'error': 'token_expired'}), 401

@jwt.invalid_token_loader
def invalid_token_callback(error):
    return jsonify({'message': 'Invalid token', 'error': 'invalid_token'}), 401

@jwt.unauthorized_loader
def missing_token_callback(error):
    return jsonify({'message': 'Missing token', 'error': 'authorization_required'}), 401

@jwt.revoked_token_loader
def revoked_token_callback(jwt_header, jwt_payload):
    return jsonify({'message': 'Token revoked', 'error': 'token_revoked'}), 401

@jwt.needs_fresh_token_loader
def token_not_fresh_callback(jwt_header, jwt_payload):
    return jsonify({'message': 'Token not fresh', 'error': 'fresh_token_required'}), 401

# File Serving Routes
@app.route('/uploads/products/<path:filename>')
def serve_product_files(filename):
    try:
        return send_from_directory(PRODUCTS_UPLOAD_FOLDER, filename)
    except FileNotFoundError:
        return jsonify({'error': 'File not found'}), 404
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/static/uploads/<path:filename>')
def serve_uploaded_files(filename):
    try:
        return send_from_directory(UPLOAD_FOLDER, filename)
    except FileNotFoundError:
        return jsonify({'error': 'File not found'}), 404
    except Exception as e:
        return jsonify({'error': str(e)}), 500

# Health Check
@app.route('/health', methods=['GET'])
def health_check():
    return jsonify({
        'status': 'healthy',
        'message': 'API is running',
        'version': '1.0.0',
        'jwt_config': {
            'access_token_expires': str(app.config['JWT_ACCESS_TOKEN_EXPIRES']),
            'refresh_token_expires': str(app.config['JWT_REFRESH_TOKEN_EXPIRES'])
        }
    }), 200

@app.route('/', methods=['GET'])
def index():
    return jsonify({
        'name': 'Abesekara POS API',
        'version': '1.0.0',
        'status': 'running'
    }), 200

# Register Blueprints
app.register_blueprint(login_bp)
app.register_blueprint(product_bp)
app.register_blueprint(supplier_bp)
app.register_blueprint(customer_bp)
app.register_blueprint(user_bp)
app.register_blueprint(grn_bp)
app.register_blueprint(prescription_bp)
app.register_blueprint(patient_history_bp)
app.register_blueprint(purchase_bp)
app.register_blueprint(purchase_return_bp)
app.register_blueprint(sale_bp)
app.register_blueprint(sale_return_bp)
app.register_blueprint(warehouse_bp)
app.register_blueprint(stores_bp)
app.register_blueprint(adjustment_bp)
app.register_blueprint(stock_transfer_bp)
app.register_blueprint(variation_bp)
app.register_blueprint(expenses_bp)
app.register_blueprint(quotation_bp)
app.register_blueprint(payment_methods_bp)
app.register_blueprint(barcode_bp)
app.register_blueprint(cashier_bp)
app.register_blueprint(report_bp)
app.register_blueprint(doctor_bp)
app.register_blueprint(appoinment_bp)
app.register_blueprint(session_bp)
app.register_blueprint(charge_bp)
app.register_blueprint(lab_bill_bp)




# Error Handlers
@app.errorhandler(400)
def bad_request(error):
    return jsonify({'error': 'Bad Request'}), 400

@app.errorhandler(401)
def unauthorized(error):
    return jsonify({'error': 'Unauthorized'}), 401

@app.errorhandler(403)
def forbidden(error):
    return jsonify({'error': 'Forbidden'}), 403

@app.errorhandler(404)
def not_found(error):
    return jsonify({'error': 'Not Found'}), 404

@app.errorhandler(413)
def request_entity_too_large(error):
    return jsonify({'error': 'File too large. Max: 16MB'}), 413

@app.errorhandler(500)
def internal_server_error(error):
    print(f"Error: {str(error)}")
    return jsonify({'error': 'Internal Server Error'}), 500

@app.errorhandler(Exception)
def handle_exception(error):
    print(f"Unhandled Exception: {str(error)}")
    return jsonify({'error': 'Internal Server Error'}), 500

# Request Hooks
@app.before_request
def log_request_info():
    if app.debug:
        print(f"Request: {request.method} {request.path}")

@app.after_request
def after_request(response):
    response.headers['X-Content-Type-Options'] = 'nosniff'
    response.headers['X-Frame-Options'] = 'DENY'
    response.headers['X-XSS-Protection'] = '1; mode=block'
    return response

if __name__ == "__main__":
    print("="*60)
    print("🚀 Abesekara POS API Server Starting...")
    print("="*60)
    print(f"📍 Server: http://0.0.0.0:5000")
    print(f"🌐 Frontend: {FRONTEND_URL}")
    print(f"🔐 Access Token: 1 hour")
    print(f"🔑 Refresh Token: 24 hours")
    print(f"⏰ Session Duration: 24 hours with auto-refresh")
    print("="*60)
    
    app.run(host='0.0.0.0', port=5000, debug=True, threaded=True)