import os
import json
import shutil
import sqlite3
from datetime import datetime
from flask import Blueprint, jsonify, request, session, send_file
from core.db import get_db
from core.config import DB_PATH
from core.security import hash_pw
import zipfile
import io
import tempfile

settings_bp = Blueprint('settings', __name__)


def require_login(f):
    from functools import wraps
    @wraps(f)
    def decorated(*args, **kwargs):
        if not session.get('giris'):
            return jsonify({'ok': False, 'hata': 'Oturum açık değil'}), 401
        return f(*args, **kwargs)
    return decorated


def ayar_get(db, key, default=None):
    row = db.execute(
        "SELECT deger FROM ayarlar WHERE anahtar=?", (key,)
    ).fetchone()
    return row['deger'] if row else default


def ayar_set(db, key, value):
    db.execute(
        "INSERT OR REPLACE INTO ayarlar (anahtar, deger) VALUES (?, ?)",
        (key, str(value))
    )


@settings_bp.route('/api/ayarlar', methods=['GET'])
@require_login
def get_ayarlar():
    db = get_db()
    return jsonify({
        'ok': True,
        'dukkan_adi': ayar_get(db, 'dukkan_adi', ''),
        'tema': ayar_get(db, 'tema', 'light'),
        'otomatik_kilit_dk': ayar_get(db, 'otomatik_kilit_dk', '0'),
        'yedek_hatirlat_gun': ayar_get(db, 'yedek_hatirlat_gun', '0'),
        'son_yedek_tarihi': ayar_get(db, 'son_yedek_tarihi', ''),
    })


@settings_bp.route('/api/ayarlar/dukkan', methods=['POST'])
@require_login
def update_dukkan():
    d = request.json or {}
    yeni_ad = (d.get('dukkan_adi') or '').strip()
    if not yeni_ad:
        return jsonify({'ok': False, 'hata': 'Dükkan adı boş olamaz'})
    db = get_db()
    ayar_set(db, 'dukkan_adi', yeni_ad)
    db.commit()
    return jsonify({'ok': True, 'dukkan_adi': yeni_ad})


@settings_bp.route('/api/ayarlar/parola', methods=['POST'])
@require_login
def update_parola():
    d = request.json or {}
    mevcut = (d.get('mevcut_parola') or '').strip()
    yeni = (d.get('yeni_parola') or '').strip()
    tekrar = (d.get('yeni_parola_tekrar') or '').strip()

    if len(yeni) < 4:
        return jsonify({'ok': False, 'hata': 'Yeni parola en az 4 karakter olmalı'})
    if yeni != tekrar:
        return jsonify({'ok': False, 'hata': 'Parolalar eşleşmiyor'})

    db = get_db()
    mevcut_hash = ayar_get(db, 'parola_hash', '')
    if mevcut_hash != hash_pw(mevcut):
        return jsonify({'ok': False, 'hata': 'Mevcut parola yanlış'})

    ayar_set(db, 'parola_hash', hash_pw(yeni))
    db.commit()
    return jsonify({'ok': True})


@settings_bp.route('/api/ayarlar/tema', methods=['POST'])
@require_login
def update_tema():
    d = request.json or {}
    tema = d.get('tema', 'light')
    if tema not in ('light', 'dark', 'sistem'):
        return jsonify({'ok': False, 'hata': 'Geçersiz tema'})
    db = get_db()
    ayar_set(db, 'tema', tema)
    db.commit()
    return jsonify({'ok': True, 'tema': tema})


@settings_bp.route('/api/ayarlar/kilit', methods=['POST'])
@require_login
def update_kilit():
    d = request.json or {}
    dk = str(d.get('otomatik_kilit_dk', '0'))
    db = get_db()
    ayar_set(db, 'otomatik_kilit_dk', dk)
    db.commit()
    return jsonify({'ok': True, 'otomatik_kilit_dk': dk})


@settings_bp.route('/api/ayarlar/yedek-hatirlat', methods=['POST'])
@require_login
def update_yedek_hatirlat():
    d = request.json or {}
    gun = str(d.get('yedek_hatirlat_gun', '0'))
    db = get_db()
    ayar_set(db, 'yedek_hatirlat_gun', gun)
    db.commit()
    return jsonify({'ok': True, 'yedek_hatirlat_gun': gun})


@settings_bp.route('/api/yedek/indir', methods=['GET'])
@require_login
def yedek_indir():
    if not os.path.exists(DB_PATH):
        return jsonify({'ok': False, 'hata': 'Veritabanı bulunamadı'}), 404

    now = datetime.now()
    # Format: DDMMYYYYHHMM  →  090420261413
    dosya_adi = now.strftime('%d%m%Y%H%M') + '.zip'

    # JSON verisini hazırla
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    tablolar = ['ayarlar', 'musteriler', 'urunler', 'satislar', 'stok_hareketleri', 'odemeler']
    veri = {}
    for tablo in tablolar:
        try:
            rows = conn.execute(f"SELECT * FROM {tablo}").fetchall()
            veri[tablo] = [dict(r) for r in rows]
        except Exception:
            veri[tablo] = []
    conn.close()

    json_bytes = json.dumps(veri, ensure_ascii=False, indent=2).encode('utf-8')
    json_adi = now.strftime('%d%m%Y%H%M') + '.json'
    db_adi = now.strftime('%d%m%Y%H%M') + '.db'

    # ZIP oluştur (hem .db hem .json içinde)
    zip_buf = io.BytesIO()
    with zipfile.ZipFile(zip_buf, 'w', zipfile.ZIP_DEFLATED) as zf:
        zf.write(DB_PATH, db_adi)
        zf.writestr(json_adi, json_bytes)
    zip_buf.seek(0)

    # Son yedek tarihini kaydet (tarih + saat)
    db = get_db()
    ayar_set(db, 'son_yedek_tarihi', now.strftime('%Y-%m-%d %H:%M'))
    db.commit()

    return send_file(
        zip_buf,
        as_attachment=True,
        download_name=dosya_adi,
        mimetype='application/zip'
    )


@settings_bp.route('/api/yedek/yukle', methods=['POST'])
@require_login
def yedek_yukle():
    if 'dosya' not in request.files:
        return jsonify({'ok': False, 'hata': 'Dosya seçilmedi'})

    f = request.files['dosya']
    if not f.filename.endswith('.zip'):
        return jsonify({'ok': False, 'hata': 'Sadece .zip dosyası yüklenebilir'})

    # Mevcut DB'yi yedekle
    yedek_yol = DB_PATH + '.onceki_yedek'
    try:
        shutil.copy2(DB_PATH, yedek_yol)
    except Exception:
        pass

    try:
        zip_bytes = io.BytesIO(f.read())
        with zipfile.ZipFile(zip_bytes, 'r') as zf:
            # İçindeki .db dosyasını bul
            db_dosyasi = next((n for n in zf.namelist() if n.endswith('.db')), None)
            if not db_dosyasi:
                return jsonify({'ok': False, 'hata': 'ZIP içinde .db dosyası bulunamadı'})

            # Geçici dosyaya çıkar ve doğrula
            tmp = tempfile.NamedTemporaryFile(delete=False, suffix='.db')
            tmp.write(zf.read(db_dosyasi))
            tmp.close()

            test_conn = sqlite3.connect(tmp.name)
            test_conn.execute("SELECT * FROM ayarlar LIMIT 1").fetchall()
            test_conn.close()

            shutil.copy2(tmp.name, DB_PATH)
            os.unlink(tmp.name)

        return jsonify({'ok': True, 'mesaj': 'Yedek başarıyla yüklendi. Sayfa yenileniyor...'})
    except Exception as e:
        try:
            shutil.copy2(yedek_yol, DB_PATH)
        except Exception:
            pass
        return jsonify({'ok': False, 'hata': f'Geçersiz yedek dosyası: {str(e)}'})


@settings_bp.route('/api/ayarlar/yedek-kontrol', methods=['GET'])
@require_login
def yedek_kontrol():
    """Frontend'in yedek hatırlatması için son yedek tarihini döndürür."""
    db = get_db()
    gun_str = ayar_get(db, 'yedek_hatirlat_gun', '0')
    son_yedek = ayar_get(db, 'son_yedek_tarihi', '')

    try:
        gun = int(gun_str)
    except Exception:
        gun = 0

    if gun == 0 or not son_yedek:
        return jsonify({'ok': True, 'hatirlat': False})

    try:
        # Hem 'YYYY-MM-DD HH:MM' hem 'YYYY-MM-DD' formatını destekle
        fmt = '%Y-%m-%d %H:%M' if ' ' in son_yedek else '%Y-%m-%d'
        son = datetime.strptime(son_yedek, fmt)
        fark = (datetime.now() - son).days
        hatirlat = fark >= gun
    except Exception:
        hatirlat = False

    return jsonify({'ok': True, 'hatirlat': hatirlat, 'gun_gecti': fark if son_yedek else 0})
