"""
views.py

Purpose:
  User-facing HTML pages that are not pure APIs: login/logout, selection page,
  add camera page. This blueprint wires routes and uses shared services.

Routes:
  - GET/POST /, /login: login
  - GET /logout: logout
  - GET /select: main selection page shell
  - GET/POST /dodaj-kameru: add camera form
"""

import re
from datetime import datetime, timedelta
from flask import Blueprint, render_template, request, redirect, url_for, session, flash, make_response
from .db import get_db
from .security import login_required
from .rate_limit import is_login_allowed, is_ip_allowed, record_login_failure, record_login_success, record_ip_failure
from .security_enhancements import secure_password_check
from .audit import log_auth_event, get_request_ip


bp = Blueprint('views', __name__)


@bp.route('/', methods=['GET', 'POST'], endpoint='login_root')
@bp.route('/login', methods=['GET', 'POST'], endpoint='login_login')
def login():
    import bcrypt
    if request.method == 'POST':
        username = request.form.get('username', '').strip().lower()
        password = request.form.get('password', '')
        # Rate limit per (username, ip)
        client_ip = get_request_ip(request) or ''
        allowed_user, retry_after_user = is_login_allowed(username, client_ip)
        allowed_ip, retry_after_ip = is_ip_allowed(client_ip)
        if not allowed_user or not allowed_ip:
            flash('Previše pokušaja. Pokušajte ponovno kasnije.', 'error')
            try:
                # escalate IP counter even if we blocked before credential check
                record_ip_failure(client_ip)
            except Exception:
                pass
            try:
                log_auth_event('login_rate_limited', username=username, ip=client_ip)
            except Exception:
                pass
            resp = make_response(render_template('login.html'))
            resp.headers['Retry-After'] = str(max(retry_after_user, retry_after_ip))
            return resp, 429
        db = get_db()
        cur = db.execute('SELECT * FROM users WHERE LOWER(username) = ?', (username,))
        user = cur.fetchone()
        # Use timing-attack resistant password verification
        if secure_password_check(username, password, user):
            # Regenerate session to prevent fixation
            session.clear()
            session['user_id'] = user['id']
            record_login_success(username, client_ip)
            try:
                log_auth_event('login_success', username=username, user_id=user['id'], ip=client_ip)
            except Exception:
                pass
            return redirect(url_for('views.select_page'))
        # Record failed attempt
        try:
            record_login_failure(username, client_ip)
        except Exception:
            pass
        try:
            log_auth_event('login_failure', username=username, ip=client_ip)
        except Exception:
            pass
        flash('Pogrešno korisničko ime ili lozinka.', 'error')
        # Use the root endpoint to avoid hosts that block /login
        return redirect(url_for('views.login_root'))
    return render_template('login.html')


# Alias to avoid potential upstream restrictions on /login path in some hosts/WAFs
@bp.route('/auth/login', methods=['POST'])
def login_post_alias():
    return login()


@bp.route('/logout', methods=['POST'])
def logout():
    session.pop('user_id', None)
    return redirect('/')


@bp.route('/select')
@login_required
def select_page():
    # Server renders shell; data fetched via /api/kamere
    return render_template('select.html')


@bp.route('/dodaj-kameru', methods=['GET', 'POST'])
@login_required
def add_camera_redesign():
    if request.method == 'POST':
        # CSRF protection is enforced globally in initializer
        camera_id = (request.form.get('camera_id') or '').strip()
        camera_name = (request.form.get('camera_name') or '').strip()
        if not camera_id.isdigit() or len(camera_id) != 12:
            flash('Broj kamere mora imati točno 12 znamenki.', 'error')
            return redirect(url_for('views.add_camera_redesign'))
        if not camera_name:
            flash('Ime kamere je obavezno.', 'error')
            return redirect(url_for('views.add_camera_redesign'))
        db = get_db()
        import sqlite3
        try:
            db.execute(
                'INSERT OR IGNORE INTO cameras (user_id, camera_id, camera_name) VALUES (?, ?, ?)',
                (session['user_id'], camera_id, camera_name),
            )
            db.commit()
            flash('Kamera je dodana.', 'success')
        except sqlite3.Error:
            flash('Dogodila se greška. Pokušajte ponovno.', 'error')
        return redirect(url_for('views.select_page'))
    return render_template('add_camera.html')


