"""
gallery.py

Purpose:
  Gallery pages and image deletion API. Uses the images_service to enumerate and
  group images by time.

Routes:
  - GET /galerija
  - GET /galerija/<int:camera_id>
  - GET /slika?rel=...
  - POST /api/image/delete
"""

import os
import sqlite3
from flask import Blueprint, render_template, request, redirect, url_for, jsonify, session, abort
from .security import login_required
from .db import get_db
from .paths import STATIC_PATH, USER_PHOTOS_REAL
from .helpers import parse_ts_from_any, format_dt, normalize_to_static_user_photos, build_media_url, resolve_media_token, build_share_url
from .images_service import collect_user_images, group_images_by_time


bp = Blueprint('gallery', __name__)


@bp.route('/galerija')
@login_required
def gallery_all():
    images = collect_user_images(session['user_id'], get_db(), STATIC_PATH)
    grouped = group_images_by_time(images)
    sections = []
    for sec in grouped:
        items = [{'url': build_media_url(it['rel']), 'rel': it['rel'], 'ts': format_dt(it['ts']) if it['ts'] else ''} for it in sec['items']]
        sections.append({'title': sec['title'], 'items': items})
    return render_template('gallery_all.html', sections=sections)


@bp.route('/galerija/<int:camera_id>')
@login_required
def camera_gallery(camera_id: int):
    cam_id_str = str(camera_id)
    db = get_db()
    row = db.execute('SELECT camera_name FROM cameras WHERE user_id=? AND camera_id=?', (session['user_id'], camera_id)).fetchone()
    if not row:
        abort(404)
    camera_name = row['camera_name']
    # Scan filesystem for this camera id
    images = []
    root = os.path.join(STATIC_PATH, 'User-photos')
    for dirpath, _, files in os.walk(root):
        for name in files:
            if not name.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')):
                continue
            ts, cam = parse_ts_from_any(name)
            if cam == cam_id_str:
                abs_path = os.path.join(dirpath, name)
                rel = os.path.relpath(abs_path, STATIC_PATH).replace('\\', '/')
                ts = ts or os.path.getmtime(abs_path)
                images.append({'url': build_media_url(rel), 'rel': rel, 'ts': ts})
    grouped = group_images_by_time(images)
    sections = []
    for sec in grouped:
        items = [{'url': build_media_url(it['rel']), 'rel': it['rel'], 'ts': format_dt(it['ts']) if it['ts'] else ''} for it in sec['items']]
        sections.append({'title': sec['title'], 'items': items})
    return render_template('camera_gallery.html', camera_id=camera_id, camera_name=camera_name, sections=sections)


@bp.route('/slika')
@login_required
def image_detail():
    rel_or_token = request.args.get('rel', type=str, default='')
    if not rel_or_token:
        return redirect(url_for('gallery.gallery_all'))
    # Accept either a raw rel path (legacy) or a signed token
    rel = resolve_media_token(rel_or_token) or normalize_to_static_user_photos(rel_or_token)
    ts, cam = parse_ts_from_any(rel)
    if not cam:
        abort(404)
    # Ownership enforcement: ensure the camera belongs to the current user
    db = get_db()
    owner = db.execute('SELECT 1 FROM cameras WHERE user_id=? AND camera_id=?', (session['user_id'], cam)).fetchone()
    if not owner:
        abort(404)
    return render_template('image_detail.html', image_url=build_media_url(rel), timestamp=format_dt(ts) if ts else '', tags=['Image'], rel=rel)


@bp.route('/api/image/delete', methods=['POST'])
@login_required
def api_delete_image():
    data = request.get_json(silent=True) or {}
    rel = normalize_to_static_user_photos(data.get('rel', ''))
    if not rel:
        return jsonify({'success': False, 'message': 'Nedostaje slika.'}), 400
    # Validate camera ownership by parsing camera id from filename
    _, cam = parse_ts_from_any(rel)
    if not cam:
        return jsonify({'success': False, 'message': 'Neispravno ime datoteke.'}), 400
    db = get_db()
    owner = db.execute('SELECT 1 FROM cameras WHERE user_id=? AND camera_id=?', (session['user_id'], cam)).fetchone()
    if not owner:
        return jsonify({'success': False, 'message': 'Nedozvoljeno.'}), 403
    # Remove file from disk if it is under STATIC_PATH
    abs_path = os.path.join(STATIC_PATH, rel)
    real_static = USER_PHOTOS_REAL if rel.startswith('User-photos/') else os.path.realpath(STATIC_PATH)
    real_abs = os.path.realpath(abs_path)
    # Ensure path is within STATIC_PATH
    if not real_abs.startswith(real_static):
        return jsonify({'success': False, 'message': 'Putanja nije dozvoljena.'}), 400
    if os.path.exists(abs_path):
        # Deletion requires write permission on the containing directory, not on the file itself
        parent_dir = os.path.dirname(abs_path)
        if not os.access(parent_dir, os.W_OK):
            return jsonify({'success': False, 'message': 'Server nema dozvolu za brisanje datoteke.'}), 403
        try:
            os.remove(abs_path)
        except PermissionError:
            return jsonify({'success': False, 'message': 'Server nema dozvolu za brisanje datoteke.'}), 403
        except OSError:
            return jsonify({'success': False, 'message': 'Ne mogu obrisati datoteku.'}), 500
    # Remove from DB paths if present
    try:
        row = db.execute('SELECT file_paths FROM cameras WHERE user_id=? AND camera_id=?', (session['user_id'], cam)).fetchone()
        if row and row['file_paths']:
            fps = [p.strip() for p in row['file_paths'].split(',') if p.strip()]
            # match by normalized path or just filename
            name_only = os.path.basename(rel)
            kept = [p for p in fps if (os.path.basename(p) != name_only) and (normalize_to_static_user_photos(p) != rel)]
            db.execute('UPDATE cameras SET file_paths=? WHERE user_id=? AND camera_id=?', (','.join(kept), session['user_id'], cam))
            db.commit()
    except sqlite3.Error:
        # Do not fail deletion if DB update fails; image removal already done
        pass
    return jsonify({'success': True})


@bp.route('/share_link', methods=['POST'])
@login_required
def user_generate_share_link():
    """Generate a short-lived public share URL for an image owned by the current user.
    Body: { rel: 'User-photos/PICT_...', ttl_minutes: 30 }
    """
    data = request.get_json(silent=True) or {}
    rel = normalize_to_static_user_photos(str(data.get('rel') or ''))
    ttl_minutes = int(data.get('ttl_minutes') or 14*24*60)
    ttl_minutes = max(1, min(ttl_minutes, 24*60))
    if not rel:
        return jsonify({'success': False, 'message': 'Nedostaje slika.'}), 400
    ts, cam = parse_ts_from_any(rel)
    if not cam:
        return jsonify({'success': False, 'message': 'Neispravno ime datoteke.'}), 400
    # Verify ownership
    db = get_db()
    owner = db.execute('SELECT 1 FROM cameras WHERE user_id=? AND camera_id=?', (session['user_id'], cam)).fetchone()
    if not owner:
        return jsonify({'success': False, 'message': 'Nedozvoljeno.'}), 403
    # Verify file exists
    abs_path = os.path.join(STATIC_PATH, rel)
    if not os.path.exists(abs_path):
        return jsonify({'success': False, 'message': 'Datoteka ne postoji.'}), 404
    # Build share URL
    import time
    exp = int(time.time()) + ttl_minutes * 60
    url = build_share_url(rel, exp)
    return jsonify({'success': True, 'url': url, 'expires_at': exp})


