from flask import Flask, render_template, request, redirect, url_for, flash, send_from_directory, session
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from datetime import datetime
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = 'ijcmse-secret-key-change-in-production'
if os.name == "posix":
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://tezloans_ijcmse:TESTdata123@148.113.4.193/tezloans_ijcmse'
else:
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///ijcmse.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
    'pool_pre_ping': True,
    'pool_recycle': 25
}
app.config['UPLOAD_FOLDER'] = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'uploads')
app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024  # 50MB max file size
ALLOWED_EXTENSIONS = {'pdf', 'docx', 'doc', 'txt'}

# Ensure upload folder exists
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.login_view = 'admin_login'

# ==================== DATABASE MODELS ====================

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(256), nullable=False)
    is_admin = db.Column(db.Boolean, default=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)


class Editor(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(200), nullable=False)
    affiliation = db.Column(db.String(500))
    country = db.Column(db.String(100))
    email = db.Column(db.String(120))
    role = db.Column(db.String(100), default='Editorial Board Member')  # Editor-in-Chief, Associate Editor, etc.
    order = db.Column(db.Integer, default=0)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)


class Volume(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    volume_number = db.Column(db.Integer, nullable=False)
    year = db.Column(db.Integer, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    issues = db.relationship('Issue', backref='volume', lazy=True, cascade='all, delete-orphan')


class Issue(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    issue_number = db.Column(db.Integer, nullable=False)
    volume_id = db.Column(db.Integer, db.ForeignKey('volume.id'), nullable=False)
    is_online_ready = db.Column(db.Boolean, default=False)
    publication_date = db.Column(db.Date)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    articles = db.relationship('Article', backref='issue', lazy=True, cascade='all, delete-orphan')


class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(500), nullable=False)
    authors = db.Column(db.Text, nullable=False)
    abstract = db.Column(db.Text)
    keywords = db.Column(db.String(500))
    doi = db.Column(db.String(100))
    pages = db.Column(db.String(50))
    issue_id = db.Column(db.Integer, db.ForeignKey('issue.id'), nullable=False)
    pdf_filename = db.Column(db.String(255))
    is_open_access = db.Column(db.Boolean, default=False)
    published_date = db.Column(db.Date)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)


class Submission(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(500), nullable=False)
    authors = db.Column(db.Text, nullable=False)
    email = db.Column(db.String(120), nullable=False)
    abstract = db.Column(db.Text, nullable=False)
    keywords = db.Column(db.String(500))
    filename = db.Column(db.String(255), nullable=False)
    original_filename = db.Column(db.String(255), nullable=False)
    status = db.Column(db.String(50), default='pending')  # pending, under_review, accepted, rejected
    submitted_at = db.Column(db.DateTime, default=datetime.utcnow)
    notes = db.Column(db.Text)


class Contact(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(200), nullable=False)
    email = db.Column(db.String(120), nullable=False)
    subject = db.Column(db.String(300), nullable=False)
    message = db.Column(db.Text, nullable=False)
    is_read = db.Column(db.Boolean, default=False)
    submitted_at = db.Column(db.DateTime, default=datetime.utcnow)


@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


# ==================== PUBLIC ROUTES ====================

@app.route('/')
def index():
    # Get latest volume and issue
    latest_volume = Volume.query.order_by(Volume.year.desc(), Volume.volume_number.desc()).first()
    volumes = Volume.query.order_by(Volume.year.desc()).all()
    return render_template('index.html', latest_volume=latest_volume, volumes=volumes)


@app.route('/aims-scope')
def aims_scope():
    return render_template('aims_scope.html')


@app.route('/editorial-board')
def editorial_board():
    editors = Editor.query.order_by(Editor.order, Editor.name).all()
    # Group editors by role
    editors_by_role = {}
    for editor in editors:
        if editor.role not in editors_by_role:
            editors_by_role[editor.role] = []
        editors_by_role[editor.role].append(editor)
    return render_template('editorial_board.html', editors_by_role=editors_by_role)


@app.route('/submission-guidelines')
def submission_guidelines():
    return render_template('submission_guidelines.html')


@app.route('/call-for-papers')
def call_for_papers():
    return render_template('call_for_papers.html')


@app.route('/peer-review-policy')
def peer_review_policy():
    return render_template('peer_review_policy.html')


@app.route('/ethical-policy')
def ethical_policy():
    return render_template('ethical_policy.html')


@app.route('/open-access')
def open_access():
    return render_template('open_access.html')


@app.route('/abstracted-indexed')
def abstracted_indexed():
    return render_template('abstracted_indexed.html')


@app.route('/contact', methods=['GET', 'POST'])
def contact():
    if request.method == 'POST':
        name = request.form.get('name')
        email = request.form.get('email')
        subject = request.form.get('subject')
        message = request.form.get('message')
        
        if name and email and subject and message:
            contact_msg = Contact(name=name, email=email, subject=subject, message=message)
            db.session.add(contact_msg)
            db.session.commit()
            flash('Your message has been sent successfully!', 'success')
            return redirect(url_for('contact'))
        else:
            flash('Please fill in all fields.', 'error')
    
    return render_template('contact.html')


@app.route('/submit-article', methods=['GET', 'POST'])
def submit_article():
    if request.method == 'POST':
        title = request.form.get('title')
        authors = request.form.get('authors')
        email = request.form.get('email')
        abstract = request.form.get('abstract')
        keywords = request.form.get('keywords')
        file = request.files.get('manuscript')
        
        if not all([title, authors, email, abstract, file]):
            flash('Please fill in all required fields and upload your manuscript.', 'error')
            return redirect(url_for('submit_article'))
        
        if file and allowed_file(file.filename):
            original_filename = secure_filename(file.filename)
            # Create unique filename
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            filename = f"{timestamp}_{original_filename}"
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            
            submission = Submission(
                title=title,
                authors=authors,
                email=email,
                abstract=abstract,
                keywords=keywords,
                filename=filename,
                original_filename=original_filename
            )
            db.session.add(submission)
            db.session.commit()
            flash('Your manuscript has been submitted successfully!', 'success')
            return redirect(url_for('submit_article'))
        else:
            flash('Invalid file type. Please upload PDF, DOCX, DOC, or TXT files only.', 'error')
    
    return render_template('submit_article.html')


@app.route('/volumes')
def volumes():
    all_volumes = Volume.query.order_by(Volume.year.desc(), Volume.volume_number.desc()).all()
    # Group by decade
    volumes_by_decade = {}
    for vol in all_volumes:
        decade = (vol.year // 10) * 10
        decade_key = f"{decade}s"
        if decade_key not in volumes_by_decade:
            volumes_by_decade[decade_key] = {}
        if vol.year not in volumes_by_decade[decade_key]:
            volumes_by_decade[decade_key][vol.year] = []
        volumes_by_decade[decade_key][vol.year].append(vol)
    return render_template('volumes.html', volumes_by_decade=volumes_by_decade)


@app.route('/volume/<int:volume_id>')
def view_volume(volume_id):
    volume = Volume.query.get_or_404(volume_id)
    return render_template('view_volume.html', volume=volume)


@app.route('/issue/<int:issue_id>')
def view_issue(issue_id):
    issue = Issue.query.get_or_404(issue_id)
    articles = Article.query.filter_by(issue_id=issue_id).order_by(Article.pages).all()
    return render_template('view_issue.html', issue=issue, articles=articles)


@app.route('/article/<int:article_id>')
def view_article(article_id):
    article = Article.query.get_or_404(article_id)
    return render_template('view_article.html', article=article)


@app.route('/online-ready')
def online_ready():
    issues = Issue.query.filter_by(is_online_ready=True).all()
    articles = []
    for issue in issues:
        articles.extend(issue.articles)
    return render_template('online_ready.html', articles=articles)


# ==================== ADMIN ROUTES ====================

@app.route('/admin/login', methods=['GET', 'POST'])
def admin_login():
    if current_user.is_authenticated:
        return redirect(url_for('admin_dashboard'))
    
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.query.filter_by(username=username, is_admin=True).first()
        
        if user and user.check_password(password):
            login_user(user)
            flash('Logged in successfully!', 'success')
            return redirect(url_for('admin_dashboard'))
        else:
            flash('Invalid username or password.', 'error')
    
    return render_template('admin/login.html')


@app.route('/admin/logout')
@login_required
def admin_logout():
    logout_user()
    flash('Logged out successfully.', 'success')
    return redirect(url_for('admin_login'))


@app.route('/admin')
@login_required
def admin_dashboard():
    stats = {
        'users': User.query.count(),
        'editors': Editor.query.count(),
        'volumes': Volume.query.count(),
        'issues': Issue.query.count(),
        'articles': Article.query.count(),
        'pending_submissions': Submission.query.filter_by(status='pending').count(),
        'unread_contacts': Contact.query.filter_by(is_read=False).count()
    }
    recent_submissions = Submission.query.order_by(Submission.submitted_at.desc()).limit(5).all()
    recent_contacts = Contact.query.order_by(Contact.submitted_at.desc()).limit(5).all()
    return render_template('admin/dashboard.html', stats=stats, recent_submissions=recent_submissions, recent_contacts=recent_contacts)


# User Management
@app.route('/admin/users')
@login_required
def admin_users():
    users = User.query.order_by(User.created_at.desc()).all()
    return render_template('admin/users.html', users=users)


@app.route('/admin/users/add', methods=['GET', 'POST'])
@login_required
def admin_add_user():
    if request.method == 'POST':
        username = request.form.get('username')
        email = request.form.get('email')
        password = request.form.get('password')
        is_admin = request.form.get('is_admin') == 'on'
        
        if User.query.filter_by(username=username).first():
            flash('Username already exists.', 'error')
            return redirect(url_for('admin_add_user'))
        
        if User.query.filter_by(email=email).first():
            flash('Email already exists.', 'error')
            return redirect(url_for('admin_add_user'))
        
        user = User(username=username, email=email, is_admin=is_admin)
        user.set_password(password)
        db.session.add(user)
        db.session.commit()
        flash('User created successfully!', 'success')
        return redirect(url_for('admin_users'))
    
    return render_template('admin/add_user.html')


@app.route('/admin/users/edit/<int:user_id>', methods=['GET', 'POST'])
@login_required
def admin_edit_user(user_id):
    user = User.query.get_or_404(user_id)
    
    if request.method == 'POST':
        user.username = request.form.get('username')
        user.email = request.form.get('email')
        user.is_admin = request.form.get('is_admin') == 'on'
        
        if request.form.get('password'):
            user.set_password(request.form.get('password'))
        
        db.session.commit()
        flash('User updated successfully!', 'success')
        return redirect(url_for('admin_users'))
    
    return render_template('admin/edit_user.html', user=user)


@app.route('/admin/users/delete/<int:user_id>')
@login_required
def admin_delete_user(user_id):
    user = User.query.get_or_404(user_id)
    if user.id == current_user.id:
        flash('You cannot delete your own account.', 'error')
        return redirect(url_for('admin_users'))
    
    db.session.delete(user)
    db.session.commit()
    flash('User deleted successfully!', 'success')
    return redirect(url_for('admin_users'))


# Editor Management
@app.route('/admin/editors')
@login_required
def admin_editors():
    editors = Editor.query.order_by(Editor.order, Editor.name).all()
    return render_template('admin/editors.html', editors=editors)


@app.route('/admin/editors/add', methods=['GET', 'POST'])
@login_required
def admin_add_editor():
    if request.method == 'POST':
        editor = Editor(
            name=request.form.get('name'),
            affiliation=request.form.get('affiliation'),
            country=request.form.get('country'),
            email=request.form.get('email'),
            role=request.form.get('role'),
            order=int(request.form.get('order', 0))
        )
        db.session.add(editor)
        db.session.commit()
        flash('Editor added successfully!', 'success')
        return redirect(url_for('admin_editors'))
    
    return render_template('admin/add_editor.html')


@app.route('/admin/editors/edit/<int:editor_id>', methods=['GET', 'POST'])
@login_required
def admin_edit_editor(editor_id):
    editor = Editor.query.get_or_404(editor_id)
    
    if request.method == 'POST':
        editor.name = request.form.get('name')
        editor.affiliation = request.form.get('affiliation')
        editor.country = request.form.get('country')
        editor.email = request.form.get('email')
        editor.role = request.form.get('role')
        editor.order = int(request.form.get('order', 0))
        
        db.session.commit()
        flash('Editor updated successfully!', 'success')
        return redirect(url_for('admin_editors'))
    
    return render_template('admin/edit_editor.html', editor=editor)


@app.route('/admin/editors/delete/<int:editor_id>')
@login_required
def admin_delete_editor(editor_id):
    editor = Editor.query.get_or_404(editor_id)
    db.session.delete(editor)
    db.session.commit()
    flash('Editor deleted successfully!', 'success')
    return redirect(url_for('admin_editors'))


# Volume & Issue Management
@app.route('/admin/volumes')
@login_required
def admin_volumes():
    volumes = Volume.query.order_by(Volume.year.desc(), Volume.volume_number.desc()).all()
    return render_template('admin/volumes.html', volumes=volumes)


@app.route('/admin/volumes/add', methods=['GET', 'POST'])
@login_required
def admin_add_volume():
    if request.method == 'POST':
        volume = Volume(
            volume_number=int(request.form.get('volume_number')),
            year=int(request.form.get('year'))
        )
        db.session.add(volume)
        db.session.commit()
        flash('Volume added successfully!', 'success')
        return redirect(url_for('admin_volumes'))
    
    return render_template('admin/add_volume.html')


@app.route('/admin/volumes/edit/<int:volume_id>', methods=['GET', 'POST'])
@login_required
def admin_edit_volume(volume_id):
    volume = Volume.query.get_or_404(volume_id)
    
    if request.method == 'POST':
        volume.volume_number = int(request.form.get('volume_number'))
        volume.year = int(request.form.get('year'))
        db.session.commit()
        flash('Volume updated successfully!', 'success')
        return redirect(url_for('admin_volumes'))
    
    return render_template('admin/edit_volume.html', volume=volume)


@app.route('/admin/volumes/delete/<int:volume_id>')
@login_required
def admin_delete_volume(volume_id):
    volume = Volume.query.get_or_404(volume_id)
    db.session.delete(volume)
    db.session.commit()
    flash('Volume and all its issues deleted successfully!', 'success')
    return redirect(url_for('admin_volumes'))


# Issue Management
@app.route('/admin/issues/<int:volume_id>')
@login_required
def admin_issues(volume_id):
    volume = Volume.query.get_or_404(volume_id)
    issues = Issue.query.filter_by(volume_id=volume_id).order_by(Issue.issue_number).all()
    return render_template('admin/issues.html', volume=volume, issues=issues)


@app.route('/admin/issues/add/<int:volume_id>', methods=['GET', 'POST'])
@login_required
def admin_add_issue(volume_id):
    volume = Volume.query.get_or_404(volume_id)
    
    if request.method == 'POST':
        pub_date = request.form.get('publication_date')
        issue = Issue(
            issue_number=int(request.form.get('issue_number')),
            volume_id=volume_id,
            is_online_ready=request.form.get('is_online_ready') == 'on',
            publication_date=datetime.strptime(pub_date, '%Y-%m-%d').date() if pub_date else None
        )
        db.session.add(issue)
        db.session.commit()
        flash('Issue added successfully!', 'success')
        return redirect(url_for('admin_issues', volume_id=volume_id))
    
    return render_template('admin/add_issue.html', volume=volume)


@app.route('/admin/issues/edit/<int:issue_id>', methods=['GET', 'POST'])
@login_required
def admin_edit_issue(issue_id):
    issue = Issue.query.get_or_404(issue_id)
    
    if request.method == 'POST':
        issue.issue_number = int(request.form.get('issue_number'))
        issue.is_online_ready = request.form.get('is_online_ready') == 'on'
        pub_date = request.form.get('publication_date')
        issue.publication_date = datetime.strptime(pub_date, '%Y-%m-%d').date() if pub_date else None
        db.session.commit()
        flash('Issue updated successfully!', 'success')
        return redirect(url_for('admin_issues', volume_id=issue.volume_id))
    
    return render_template('admin/edit_issue.html', issue=issue)


@app.route('/admin/issues/delete/<int:issue_id>')
@login_required
def admin_delete_issue(issue_id):
    issue = Issue.query.get_or_404(issue_id)
    volume_id = issue.volume_id
    db.session.delete(issue)
    db.session.commit()
    flash('Issue and all its articles deleted successfully!', 'success')
    return redirect(url_for('admin_issues', volume_id=volume_id))


# Article Management
@app.route('/admin/articles/<int:issue_id>')
@login_required
def admin_articles(issue_id):
    issue = Issue.query.get_or_404(issue_id)
    articles = Article.query.filter_by(issue_id=issue_id).order_by(Article.pages).all()
    return render_template('admin/articles.html', issue=issue, articles=articles)


@app.route('/admin/articles/add/<int:issue_id>', methods=['GET', 'POST'])
@login_required
def admin_add_article(issue_id):
    issue = Issue.query.get_or_404(issue_id)
    
    if request.method == 'POST':
        pub_date = request.form.get('published_date')
        pdf_file = request.files.get('pdf_file')
        pdf_filename = None
        
        if pdf_file and allowed_file(pdf_file.filename):
            pdf_filename = secure_filename(pdf_file.filename)
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            pdf_filename = f"{timestamp}_{pdf_filename}"
            pdf_file.save(os.path.join(app.config['UPLOAD_FOLDER'], pdf_filename))
        
        article = Article(
            title=request.form.get('title'),
            authors=request.form.get('authors'),
            abstract=request.form.get('abstract'),
            keywords=request.form.get('keywords'),
            doi=request.form.get('doi'),
            pages=request.form.get('pages'),
            issue_id=issue_id,
            pdf_filename=pdf_filename,
            is_open_access=request.form.get('is_open_access') == 'on',
            published_date=datetime.strptime(pub_date, '%Y-%m-%d').date() if pub_date else None
        )
        db.session.add(article)
        db.session.commit()
        flash('Article added successfully!', 'success')
        return redirect(url_for('admin_articles', issue_id=issue_id))
    
    return render_template('admin/add_article.html', issue=issue)


@app.route('/admin/articles/edit/<int:article_id>', methods=['GET', 'POST'])
@login_required
def admin_edit_article(article_id):
    article = Article.query.get_or_404(article_id)
    
    if request.method == 'POST':
        article.title = request.form.get('title')
        article.authors = request.form.get('authors')
        article.abstract = request.form.get('abstract')
        article.keywords = request.form.get('keywords')
        article.doi = request.form.get('doi')
        article.pages = request.form.get('pages')
        article.is_open_access = request.form.get('is_open_access') == 'on'
        
        pub_date = request.form.get('published_date')
        article.published_date = datetime.strptime(pub_date, '%Y-%m-%d').date() if pub_date else None
        
        pdf_file = request.files.get('pdf_file')
        if pdf_file and allowed_file(pdf_file.filename):
            # Delete old file
            if article.pdf_filename:
                old_path = os.path.join(app.config['UPLOAD_FOLDER'], article.pdf_filename)
                if os.path.exists(old_path):
                    os.remove(old_path)
            
            pdf_filename = secure_filename(pdf_file.filename)
            timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
            pdf_filename = f"{timestamp}_{pdf_filename}"
            pdf_file.save(os.path.join(app.config['UPLOAD_FOLDER'], pdf_filename))
            article.pdf_filename = pdf_filename
        
        db.session.commit()
        flash('Article updated successfully!', 'success')
        return redirect(url_for('admin_articles', issue_id=article.issue_id))
    
    return render_template('admin/edit_article.html', article=article)


@app.route('/admin/articles/delete/<int:article_id>')
@login_required
def admin_delete_article(article_id):
    article = Article.query.get_or_404(article_id)
    issue_id = article.issue_id
    
    # Delete PDF file
    if article.pdf_filename:
        pdf_path = os.path.join(app.config['UPLOAD_FOLDER'], article.pdf_filename)
        if os.path.exists(pdf_path):
            os.remove(pdf_path)
    
    db.session.delete(article)
    db.session.commit()
    flash('Article deleted successfully!', 'success')
    return redirect(url_for('admin_articles', issue_id=issue_id))


# Submission Management
@app.route('/admin/submissions')
@login_required
def admin_submissions():
    submissions = Submission.query.order_by(Submission.submitted_at.desc()).all()
    return render_template('admin/submissions.html', submissions=submissions)


@app.route('/admin/submissions/view/<int:submission_id>')
@login_required
def admin_view_submission(submission_id):
    submission = Submission.query.get_or_404(submission_id)
    return render_template('admin/view_submission.html', submission=submission)


@app.route('/admin/submissions/download/<int:submission_id>')
@login_required
def admin_download_submission(submission_id):
    submission = Submission.query.get_or_404(submission_id)
    return send_from_directory(
        app.config['UPLOAD_FOLDER'],
        submission.filename,
        as_attachment=True,
        download_name=submission.original_filename
    )


@app.route('/admin/submissions/update-status/<int:submission_id>', methods=['POST'])
@login_required
def admin_update_submission_status(submission_id):
    submission = Submission.query.get_or_404(submission_id)
    submission.status = request.form.get('status')
    submission.notes = request.form.get('notes')
    db.session.commit()
    flash('Submission status updated!', 'success')
    return redirect(url_for('admin_view_submission', submission_id=submission_id))


@app.route('/admin/submissions/delete/<int:submission_id>')
@login_required
def admin_delete_submission(submission_id):
    submission = Submission.query.get_or_404(submission_id)
    
    # Delete file
    file_path = os.path.join(app.config['UPLOAD_FOLDER'], submission.filename)
    if os.path.exists(file_path):
        os.remove(file_path)
    
    db.session.delete(submission)
    db.session.commit()
    flash('Submission deleted successfully!', 'success')
    return redirect(url_for('admin_submissions'))


# Contact Management
@app.route('/admin/contacts')
@login_required
def admin_contacts():
    contacts = Contact.query.order_by(Contact.submitted_at.desc()).all()
    return render_template('admin/contacts.html', contacts=contacts)


@app.route('/admin/contacts/view/<int:contact_id>')
@login_required
def admin_view_contact(contact_id):
    contact = Contact.query.get_or_404(contact_id)
    if not contact.is_read:
        contact.is_read = True
        db.session.commit()
    return render_template('admin/view_contact.html', contact=contact)


@app.route('/admin/contacts/delete/<int:contact_id>')
@login_required
def admin_delete_contact(contact_id):
    contact = Contact.query.get_or_404(contact_id)
    db.session.delete(contact)
    db.session.commit()
    flash('Contact message deleted successfully!', 'success')
    return redirect(url_for('admin_contacts'))


# Download PDF
@app.route('/download/pdf/<int:article_id>')
def download_pdf(article_id):
    article = Article.query.get_or_404(article_id)
    if article.pdf_filename:
        return send_from_directory(
            app.config['UPLOAD_FOLDER'],
            article.pdf_filename,
            as_attachment=True
        )
    flash('PDF not available.', 'error')
    return redirect(url_for('view_article', article_id=article_id))


# ==================== SEO ROUTES ====================

@app.route('/robots.txt')
def robots_txt():
    """Serve robots.txt for search engine crawlers."""
    base_url = request.host_url.rstrip('/')
    content = f"""User-agent: *
Allow: /
Disallow: /admin/
Disallow: /uploads/

# Sitemaps
Sitemap: {base_url}/sitemap.xml

# OAI-PMH endpoint for academic harvesters
# OAI-PMH: {base_url}/oai

# API endpoints for metadata
# Articles JSON Feed: {base_url}/api/articles/metadata.json
"""
    return app.response_class(content, mimetype='text/plain')


@app.route('/sitemap.xml')
def sitemap_xml():
    """Generate XML sitemap for search engines."""
    from datetime import datetime
    pages = []
    
    # Static pages
    static_pages = [
        ('index', 1.0, 'weekly'),
        ('aims_scope', 0.8, 'monthly'),
        ('editorial_board', 0.8, 'monthly'),
        ('submission_guidelines', 0.8, 'monthly'),
        ('call_for_papers', 0.8, 'monthly'),
        ('peer_review_policy', 0.7, 'monthly'),
        ('ethical_policy', 0.7, 'monthly'),
        ('open_access', 0.7, 'monthly'),
        ('abstracted_indexed', 0.7, 'monthly'),
        ('contact', 0.6, 'monthly'),
        ('volumes', 0.9, 'weekly'),
        ('online_ready', 0.9, 'daily'),
        ('submit_article', 0.8, 'monthly'),
    ]
    
    for endpoint, priority, changefreq in static_pages:
        pages.append({
            'loc': url_for(endpoint, _external=True),
            'priority': priority,
            'changefreq': changefreq
        })
    
    # Volume pages
    volumes = Volume.query.all()
    for volume in volumes:
        pages.append({
            'loc': url_for('view_volume', volume_id=volume.id, _external=True),
            'priority': 0.7,
            'changefreq': 'monthly'
        })
    
    # Issue pages
    issues = Issue.query.all()
    for issue in issues:
        pages.append({
            'loc': url_for('view_issue', issue_id=issue.id, _external=True),
            'priority': 0.8,
            'changefreq': 'weekly'
        })
    
    # Article pages (highest priority for indexing)
    articles = Article.query.all()
    for article in articles:
        lastmod = article.published_date.strftime('%Y-%m-%d') if article.published_date else None
        pages.append({
            'loc': url_for('view_article', article_id=article.id, _external=True),
            'priority': 0.9,
            'changefreq': 'monthly',
            'lastmod': lastmod
        })
    
    xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
    xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
    
    for page in pages:
        xml += '  <url>\n'
        xml += f'    <loc>{page["loc"]}</loc>\n'
        if page.get('lastmod'):
            xml += f'    <lastmod>{page["lastmod"]}</lastmod>\n'
        xml += f'    <changefreq>{page["changefreq"]}</changefreq>\n'
        xml += f'    <priority>{page["priority"]}</priority>\n'
        xml += '  </url>\n'
    
    xml += '</urlset>'
    
    return app.response_class(xml, mimetype='application/xml')


# ==================== ACADEMIC INDEX METADATA ENDPOINTS ====================

@app.route('/oai')
def oai_pmh():
    """OAI-PMH endpoint for academic harvesters (DOAJ, OpenAIRE, BASE, etc.)"""
    verb = request.args.get('verb', 'Identify')
    identifier = request.args.get('identifier')
    metadata_prefix = request.args.get('metadataPrefix', 'oai_dc')
    
    base_url = request.url_root.rstrip('/')
    
    if verb == 'Identify':
        xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
  <responseDate>{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")}</responseDate>
  <request verb="Identify">{base_url}/oai</request>
  <Identify>
    <repositoryName>International Journal of Computational Materials Science and Engineering</repositoryName>
    <baseURL>{base_url}/oai</baseURL>
    <protocolVersion>2.0</protocolVersion>
    <adminEmail>editor@ijcmse.org</adminEmail>
    <earliestDatestamp>2010-01-01T00:00:00Z</earliestDatestamp>
    <deletedRecord>no</deletedRecord>
    <granularity>YYYY-MM-DDThh:mm:ssZ</granularity>
    <description>
      <oai-identifier xmlns="http://www.openarchives.org/OAI/2.0/oai-identifier"
                      xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai-identifier http://www.openarchives.org/OAI/2.0/oai-identifier.xsd">
        <scheme>oai</scheme>
        <repositoryIdentifier>ijcmse.org</repositoryIdentifier>
        <delimiter>:</delimiter>
        <sampleIdentifier>oai:ijcmse.org:article/1</sampleIdentifier>
      </oai-identifier>
    </description>
  </Identify>
</OAI-PMH>'''
    
    elif verb == 'ListMetadataFormats':
        xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
  <responseDate>{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")}</responseDate>
  <request verb="ListMetadataFormats">{base_url}/oai</request>
  <ListMetadataFormats>
    <metadataFormat>
      <metadataPrefix>oai_dc</metadataPrefix>
      <schema>http://www.openarchives.org/OAI/2.0/oai_dc.xsd</schema>
      <metadataNamespace>http://www.openarchives.org/OAI/2.0/oai_dc/</metadataNamespace>
    </metadataFormat>
  </ListMetadataFormats>
</OAI-PMH>'''
    
    elif verb == 'ListRecords' or verb == 'ListIdentifiers':
        articles = Article.query.join(Issue).join(Volume).order_by(Article.published_date.desc()).all()
        records = ''
        for article in articles:
            if verb == 'ListIdentifiers':
                records += f'''    <header>
      <identifier>oai:ijcmse.org:article/{article.id}</identifier>
      <datestamp>{article.published_date.strftime("%Y-%m-%dT00:00:00Z") if article.published_date else article.issue.volume.year + "-01-01T00:00:00Z"}</datestamp>
    </header>\n'''
            else:
                pub_date = article.published_date.strftime("%Y-%m-%d") if article.published_date else str(article.issue.volume.year)
                abstract_escaped = (article.abstract or '').replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
                title_escaped = article.title.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
                records += f'''    <record>
      <header>
        <identifier>oai:ijcmse.org:article/{article.id}</identifier>
        <datestamp>{article.published_date.strftime("%Y-%m-%dT00:00:00Z") if article.published_date else str(article.issue.volume.year) + "-01-01T00:00:00Z"}</datestamp>
      </header>
      <metadata>
        <oai_dc:dc xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
                   xmlns:dc="http://purl.org/dc/elements/1.1/"
                   xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd">
          <dc:title>{title_escaped}</dc:title>
          {''.join([f"<dc:creator>{author.strip()}</dc:creator>" for author in article.authors.split(',')])}
          <dc:subject>{article.keywords or 'Computational Materials Science'}</dc:subject>
          <dc:description>{abstract_escaped}</dc:description>
          <dc:publisher>IJCMSE</dc:publisher>
          <dc:date>{pub_date}</dc:date>
          <dc:type>article</dc:type>
          <dc:format>text/html</dc:format>
          <dc:identifier>{base_url}/article/{article.id}</dc:identifier>
          {f"<dc:identifier>doi:{article.doi}</dc:identifier>" if article.doi else ""}
          <dc:source>International Journal of Computational Materials Science and Engineering</dc:source>
          <dc:language>en</dc:language>
          <dc:relation>Vol. {article.issue.volume.volume_number}, No. {article.issue.issue_number}</dc:relation>
        </oai_dc:dc>
      </metadata>
    </record>\n'''
        
        element = 'ListIdentifiers' if verb == 'ListIdentifiers' else 'ListRecords'
        xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
  <responseDate>{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")}</responseDate>
  <request verb="{verb}" metadataPrefix="{metadata_prefix}">{base_url}/oai</request>
  <{element}>
{records}  </{element}>
</OAI-PMH>'''
    
    elif verb == 'GetRecord' and identifier:
        article_id = identifier.split('/')[-1] if '/' in identifier else identifier.split(':')[-1]
        article = Article.query.get(article_id)
        if article:
            pub_date = article.published_date.strftime("%Y-%m-%d") if article.published_date else str(article.issue.volume.year)
            abstract_escaped = (article.abstract or '').replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
            title_escaped = article.title.replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;')
            xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
  <responseDate>{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")}</responseDate>
  <request verb="GetRecord" identifier="{identifier}" metadataPrefix="{metadata_prefix}">{base_url}/oai</request>
  <GetRecord>
    <record>
      <header>
        <identifier>oai:ijcmse.org:article/{article.id}</identifier>
        <datestamp>{article.published_date.strftime("%Y-%m-%dT00:00:00Z") if article.published_date else str(article.issue.volume.year) + "-01-01T00:00:00Z"}</datestamp>
      </header>
      <metadata>
        <oai_dc:dc xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
                   xmlns:dc="http://purl.org/dc/elements/1.1/"
                   xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd">
          <dc:title>{title_escaped}</dc:title>
          {''.join([f"<dc:creator>{author.strip()}</dc:creator>" for author in article.authors.split(',')])}
          <dc:subject>{article.keywords or 'Computational Materials Science'}</dc:subject>
          <dc:description>{abstract_escaped}</dc:description>
          <dc:publisher>IJCMSE</dc:publisher>
          <dc:date>{pub_date}</dc:date>
          <dc:type>article</dc:type>
          <dc:format>text/html</dc:format>
          <dc:identifier>{base_url}/article/{article.id}</dc:identifier>
          {f"<dc:identifier>doi:{article.doi}</dc:identifier>" if article.doi else ""}
          <dc:source>International Journal of Computational Materials Science and Engineering</dc:source>
          <dc:language>en</dc:language>
          <dc:relation>Vol. {article.issue.volume.volume_number}, No. {article.issue.issue_number}</dc:relation>
        </oai_dc:dc>
      </metadata>
    </record>
  </GetRecord>
</OAI-PMH>'''
        else:
            xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
  <responseDate>{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")}</responseDate>
  <request verb="GetRecord" identifier="{identifier}" metadataPrefix="{metadata_prefix}">{base_url}/oai</request>
  <error code="idDoesNotExist">The identifier does not exist</error>
</OAI-PMH>'''
    else:
        xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
  <responseDate>{datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")}</responseDate>
  <request>{base_url}/oai</request>
  <error code="badVerb">Illegal OAI verb</error>
</OAI-PMH>'''
    
    return app.response_class(xml, mimetype='application/xml')


@app.route('/api/article/<int:article_id>/metadata.json')
def article_metadata_json(article_id):
    """JSON metadata endpoint for CrossRef, Semantic Scholar, and other APIs"""
    import json
    article = Article.query.get_or_404(article_id)
    base_url = request.url_root.rstrip('/')
    
    metadata = {
        "@context": "https://schema.org",
        "@type": "ScholarlyArticle",
        "title": article.title,
        "headline": article.title,
        "authors": [{"name": author.strip()} for author in article.authors.split(',')],
        "abstract": article.abstract,
        "keywords": article.keywords.split(',') if article.keywords else [],
        "datePublished": article.published_date.strftime("%Y-%m-%d") if article.published_date else str(article.issue.volume.year),
        "journal": {
            "name": "International Journal of Computational Materials Science and Engineering",
            "abbreviation": "IJCMSE",
            "issn": "2047-6841",
            "eissn": "2047-685X"
        },
        "volume": article.issue.volume.volume_number,
        "issue": article.issue.issue_number,
        "pages": article.pages,
        "doi": article.doi,
        "url": f"{base_url}/article/{article.id}",
        "pdfUrl": f"{base_url}/download-pdf/{article.id}" if article.pdf_filename else None,
        "isOpenAccess": article.is_open_access,
        "language": "en",
        "publisher": "IJCMSE"
    }
    
    return app.response_class(
        json.dumps(metadata, indent=2),
        mimetype='application/json'
    )


@app.route('/api/articles/metadata.json')
def all_articles_metadata_json():
    """JSON feed of all articles for academic aggregators"""
    import json
    articles = Article.query.join(Issue).join(Volume).order_by(Article.published_date.desc()).all()
    base_url = request.url_root.rstrip('/')
    
    items = []
    for article in articles:
        items.append({
            "id": article.id,
            "title": article.title,
            "authors": [author.strip() for author in article.authors.split(',')],
            "abstract": article.abstract,
            "keywords": article.keywords.split(',') if article.keywords else [],
            "datePublished": article.published_date.strftime("%Y-%m-%d") if article.published_date else str(article.issue.volume.year),
            "volume": article.issue.volume.volume_number,
            "issue": article.issue.issue_number,
            "pages": article.pages,
            "doi": article.doi,
            "url": f"{base_url}/article/{article.id}"
        })
    
    feed = {
        "journal": {
            "name": "International Journal of Computational Materials Science and Engineering",
            "abbreviation": "IJCMSE",
            "issn": "2047-6841",
            "eissn": "2047-685X",
            "url": base_url
        },
        "totalResults": len(items),
        "articles": items
    }
    
    return app.response_class(
        json.dumps(feed, indent=2),
        mimetype='application/json'
    )


# ==================== CLI COMMANDS ====================

@app.cli.command('init-db')
def init_db():
    """Initialize the database."""
    db.create_all()
    print('Database initialized.')


@app.cli.command('create-admin')
def create_admin():
    """Create an admin user."""
    username = input('Username: ')
    email = input('Email: ')
    password = input('Password: ')
    
    if User.query.filter_by(username=username).first():
        print('Username already exists.')
        return
    
    user = User(username=username, email=email, is_admin=True)
    user.set_password(password)
    db.session.add(user)
    db.session.commit()
    print(f'Admin user {username} created successfully!')


if __name__ == '__main__':
    with app.app_context():
        db.create_all()
        # Create default admin if not exists
        if not User.query.filter_by(username='admin').first():
            admin = User(username='admin', email='admin@ijcmse.org', is_admin=True)
            admin.set_password('admin123')
            db.session.add(admin)
            db.session.commit()
            print('Default admin created: username=admin, password=admin123')
    
    app.run(port=5001,debug=True)
