# 1. Limpeza
pkill -f streamlit
rm -f importer.py saas_users.db temp_m3u.db

# 2. Grava a V15.2 (Correção do Cache e Zero RAM)
cat << 'EOF' > importer.py
import streamlit as st
import mysql.connector
import requests
import re
import json
import os
import time
import sqlite3
import random
import string
from datetime import datetime, timedelta

# --- CONFIG ---
st.set_page_config(page_title="Xtream Admin V15.2", page_icon="💎", layout="wide")
DB_FILE = "saas_users.db"
CACHE_FILE = "temp_m3u.db"
CONFIG_FILE = "config.json"

# --- UTILITÁRIOS ---
def get_public_ip():
    try:
        return requests.get('https://api.ipify.org', timeout=2).text
    except:
        return "127.0.0.1"

def generate_code(length=8):
    chars = string.ascii_letters + string.digits
    return ''.join(random.choice(chars) for _ in range(length))

def load_config():
    default_conf = {
        'admin_user': 'admin', 
        'admin_pass': 'admin', 
        'base_url': f"http://{get_public_ip()}:7001"
    }
    if os.path.exists(CONFIG_FILE):
        try:
            with open(CONFIG_FILE, "r") as f:
                data = json.load(f)
                for k, v in default_conf.items():
                    if k not in data:
                        data[k] = v
                return data
        except:
            return default_conf
    return default_conf

def save_config(data):
    try:
        with open(CONFIG_FILE, "w") as f:
            json.dump(data, f)
    except:
        pass

config = load_config()

# --- BANCO DE DADOS LOCAL (CLIENTES) ---
def init_db():
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS users 
                 (username TEXT PRIMARY KEY, password TEXT, expire_date TEXT, 
                  target_host TEXT, target_db TEXT, target_user TEXT, target_pass TEXT)''')
    c.execute("SELECT * FROM users WHERE username='admin'")
    if not c.fetchone():
        c.execute("INSERT INTO users VALUES ('admin', 'admin', '2099-12-31', 'localhost', 'xtream_iptv', 'root', '')")
        conn.commit()
    conn.close()

def db_action(query, params=()):
    conn = sqlite3.connect(DB_FILE)
    c = conn.cursor()
    try:
        c.execute(query, params)
        conn.commit()
        res = c.fetchall()
        return res
    except:
        return None
    finally:
        conn.close()

# --- BANCO DE CACHE (IMPORTADOR) ---
def init_cache_db():
    # CORREÇÃO: Não deleta o arquivo aqui. Só cria a tabela se não existir.
    conn = sqlite3.connect(CACHE_FILE)
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS m3u_items (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, group_title TEXT, logo TEXT, url TEXT)''')
    c.execute("CREATE INDEX IF NOT EXISTS idx_group ON m3u_items (group_title)")
    conn.commit()
    conn.close()

def clear_cache():
    # Função específica para limpar só quando começa uma nova importação
    conn = sqlite3.connect(CACHE_FILE)
    c = conn.cursor()
    c.execute("DELETE FROM m3u_items")
    conn.commit()
    conn.close()

init_db()
init_cache_db()

# --- CSS PROFISSIONAL ---
st.markdown("""
    <style>
    .stApp { background-color: #0f172a; font-family: 'Segoe UI', sans-serif; }
    .status-bar { padding: 10px; margin-bottom: 20px; border-radius: 8px; font-weight: bold; text-align: center; color: white; }
    .st-online { background: #065f46; border: 1px solid #10b981; }
    .st-offline { background: #7f1d1d; border: 1px solid #ef4444; }
    .kpi-card { background: linear-gradient(135deg, #1e293b, #0f172a); padding: 20px; border-radius: 12px; border: 1px solid #334155; text-align: center; box-shadow: 0 4px 6px rgba(0,0,0,0.2); }
    .kpi-val { font-size: 2.2rem; font-weight: 800; color: #fff; }
    .kpi-lbl { color: #94a3b8; text-transform: uppercase; font-size: 0.8rem; letter-spacing: 1px; }
    .stButton>button { background: linear-gradient(45deg, #2563eb, #1d4ed8); color: white; border: none; font-weight: bold; border-radius: 6px; height: 45px; }
    .stButton>button:hover { background: #1e40af; }
    .login-box { background: #1e293b; padding: 2rem; border-radius: 15px; border: 1px solid #334155; text-align: center; }
    .copy-box { background: #020617; padding: 15px; border-radius: 8px; border: 1px dashed #475569; font-family: monospace; color: #bfdbfe; font-size: 0.9rem; text-align: left; }
    </style>
""", unsafe_allow_html=True)

# --- SESSÃO ---
if 'logged_in' not in st.session_state: st.session_state['logged_in'] = False
if 'user' not in st.session_state: st.session_state['user'] = None
if 'step' not in st.session_state: st.session_state['step'] = 1
if 'edit_mode' not in st.session_state: st.session_state['edit_mode'] = None
if 'view_mode' not in st.session_state: st.session_state['view_mode'] = None

# --- LOGIN ---
if not st.session_state['logged_in']:
    c1, c2, c3 = st.columns([1,2,1])
    with c2:
        st.markdown("<br>", unsafe_allow_html=True)
        st.markdown('<div class="login-box"><h2>💎 Painel V15.2</h2><p style="color:#94a3b8">Área do Cliente & Revenda</p></div>', unsafe_allow_html=True)
        with st.form("login"):
            u = st.text_input("Usuário")
            p = st.text_input("Senha", type="password")
            if st.form_submit_button("ACESSAR"):
                if u == config['admin_user'] and p == config['admin_pass']:
                     st.session_state['logged_in'] = True
                     st.session_state['user'] = 'admin'
                     st.rerun()
                res = db_action("SELECT * FROM users WHERE username=?", (u,))
                if res and res[0][1] == p:
                    exp = datetime.strptime(res[0][2], "%Y-%m-%d")
                    if datetime.now() > exp:
                        st.error("🚫 Plano Expirado!")
                    else:
                        st.session_state['logged_in'] = True
                        st.session_state['user'] = u
                        st.rerun()
                else:
                    st.error("Dados Inválidos")
    st.stop()

# --- ÁREA LOGADA ---
curr_user = st.session_state['user']
if curr_user == 'admin':
    user_data = ['admin', 'admin', '2099-12-31', 'localhost', 'xtream_iptv', 'root', '']
else:
    user_data = db_action("SELECT * FROM users WHERE username=?", (curr_user,))[0]

days_left = (datetime.strptime(user_data[2], "%Y-%m-%d") - datetime.now()).days
if days_left < 0 and curr_user != 'admin':
    st.error(f"🚫 ACESSO BLOQUEADO. Venceu em {user_data[2]}")
    if st.button("Sair"):
        st.session_state['logged_in']=False
        st.rerun()
    st.stop()

# CONEXÃO XTREAM
conn = None
try:
    if user_data[3]:
        conn = mysql.connector.connect(host=user_data[3], user=user_data[5], password=user_data[6], database=user_data[4], connect_timeout=3)
except:
    conn = None

if curr_user != 'admin':
    status_html = f"""<div class="status-bar {'st-online' if conn else 'st-offline'}">{'🟢 CONEXÃO XTREAM ONLINE' if conn else '🔴 CONEXÃO XTREAM OFFLINE - Configure no Menu Lateral'}</div>"""
    st.markdown(status_html, unsafe_allow_html=True)

# SIDEBAR
with st.sidebar:
    st.title(f"👤 {curr_user}")
    if curr_user == 'admin':
        st.info("🔧 Admin Config")
        with st.expander("🔗 Domínio / Link"):
            cur_url = config.get('base_url', '')
            nu = st.text_input("URL Painel", value=cur_url)
            if st.button("Salvar URL"):
                config['base_url']=nu
                save_config(config)
                st.success("Salvo!")
                time.sleep(1)
                st.rerun()
        with st.expander("🔐 Senha Admin"):
            na=st.text_input("Novo User", value=config['admin_user'])
            np=st.text_input("Nova Senha", type="password")
            if st.button("Atualizar"):
                config['admin_user']=na
                config['admin_pass']=np
                save_config(config)
                st.success("Logue novamente")
                time.sleep(2)
                st.session_state['logged_in']=False
                st.rerun()
    else:
        st.info(f"📅 Vence em: {days_left} dias")
        with st.expander("🔌 Conexão Xtream", expanded=not conn):
            nh=st.text_input("Host", value=user_data[3])
            nd=st.text_input("Banco", value=user_data[4])
            nu=st.text_input("User", value=user_data[5])
            np=st.text_input("Pass", value=user_data[6], type="password")
            if st.button("Salvar"):
                db_action("UPDATE users SET target_host=?, target_db=?, target_user=?, target_pass=? WHERE username=?", (nh, nd, nu, np, curr_user))
                st.success("Salvo!")
                time.sleep(1)
                st.rerun()
    if st.button("Sair"):
        st.session_state['logged_in']=False
        st.rerun()

# --- TABS ---
tabs = st.tabs(["📊 Dashboard", "🚀 Importador", "👑 Revenda/Admin"] if curr_user == 'admin' else ["📊 Dashboard", "🚀 Importador"])

# --- TAB 1: DASHBOARD ---
with tabs[0]:
    if curr_user == 'admin':
        users_all = db_action("SELECT expire_date FROM users WHERE username != 'admin'")
        if users_all:
            total_cli = len(users_all)
            active_cli = sum(1 for u in users_all if datetime.strptime(u[0], "%Y-%m-%d") > datetime.now())
            expired_cli = total_cli - active_cli
        else:
            total_cli = 0
            active_cli = 0
            expired_cli = 0
        c1, c2, c3 = st.columns(3)
        c1.markdown(f'<div class="kpi-card"><div class="kpi-val">{total_cli}</div><div class="kpi-lbl">Total Clientes</div></div>', unsafe_allow_html=True)
        c2.markdown(f'<div class="kpi-card"><div class="kpi-val">{active_cli}</div><div class="kpi-lbl">Ativos</div></div>', unsafe_allow_html=True)
        c3.markdown(f'<div class="kpi-card"><div class="kpi-val">{expired_cli}</div><div class="kpi-lbl">Vencidos</div></div>', unsafe_allow_html=True)
        
    elif conn:
        try:
            cur = conn.cursor()
            cur.execute("SELECT COUNT(*) FROM streams WHERE type=1")
            lv=cur.fetchone()[0]
            cur.execute("SELECT COUNT(*) FROM streams WHERE type=2")
            mv=cur.fetchone()[0]
            cur.execute("SELECT COUNT(*) FROM streams WHERE type=5")
            sr=cur.fetchone()[0]
            try:
                cur.execute("SELECT COUNT(*) FROM users")
                cl=cur.fetchone()[0]
            except:
                cl=0
            c1, c2, c3, c4 = st.columns(4)
            c1.markdown(f'<div class="kpi-card"><div class="kpi-val">{lv}</div><div class="kpi-lbl">Canais</div></div>', unsafe_allow_html=True)
            c2.markdown(f'<div class="kpi-card"><div class="kpi-val">{mv}</div><div class="kpi-lbl">Filmes</div></div>', unsafe_allow_html=True)
            c3.markdown(f'<div class="kpi-card"><div class="kpi-val">{sr}</div><div class="kpi-lbl">Séries</div></div>', unsafe_allow_html=True)
            c4.markdown(f'<div class="kpi-card"><div class="kpi-val">{cl}</div><div class="kpi-lbl">Usuários</div></div>', unsafe_allow_html=True)
        except:
            st.error("Erro na leitura do banco.")
    else:
        st.warning("Conecte seu banco de dados no menu lateral para ver seus gráficos.")

# --- TAB 2: IMPORTADOR (ANTI-CRASH) ---
with tabs[1]:
    if conn:
        # Funcoes auxiliares DB Xtream
        def get_cid(cr,cn,nm,tp):
            if not nm: nm="GERAL"
            cr.execute("SELECT id FROM stream_categories WHERE category_name=%s AND category_type=%s",(nm,tp))
            r=cr.fetchone()
            if r: return r[0]
            try:
                cr.execute("INSERT INTO stream_categories (category_type,category_name,parent_id) VALUES (%s,%s,0)",(tp,nm))
                cn.commit()
                return cr.lastrowid
            except: return 0
        
        def lnk_srv(cn,sid,svid,bids,tp):
            if not sid: return
            try:
                c=cn.cursor()
                vs=[(i,svid) for i in sid]
                c.executemany("INSERT INTO streams_sys (stream_id, server_id, parent_id, on_demand) VALUES (%s, %s, 0, 0)", vs)
                if bids:
                    col="bouquet_series" if tp=="series" else "bouquet_channels"
                    c=cn.cursor(dictionary=True)
                    for b in bids:
                        c.execute(f"SELECT {col} FROM bouquets WHERE id=%s",(b,))
                        r=c.fetchone()
                        cur=json.loads(r[col]) if r and r[col] else []
                        if not isinstance(curr, list): curr=[]
                        fin=list(set(cur+sid))
                        c.execute(f"UPDATE bouquets SET {col}=%s WHERE id=%s",(json.dumps(fin),b))
                cn.commit()
            except: pass

        def proc_to_disk(u):
            h={'User-Agent':'Mozilla/5.0'}
            rg=re.compile(r'group-title=["\']?([^"\',]+)["\']?')
            rl=re.compile(r'tvg-logo=["\']?([^"\']+)["\']?')
            stt=st.empty()
            
            # AGORA SIM: Limpa cache SÓ AQUI, no início do processo
            clear_cache()
            
            conn_cache = sqlite3.connect(CACHE_FILE)
            cc = conn_cache.cursor()
            
            try:
                with requests.get(u, headers=h, stream=True, timeout=120) as r:
                    r.raise_for_status()
                    cnt=0
                    cr={}
                    batch = []
                    
                    for l in r.iter_lines():
                        if not l: continue
                        if isinstance(l,bytes): l=l.decode('utf-8','ignore')
                        l=l.strip()
                        if l.startswith('#EXTINF'):
                            g=rg.search(l)
                            lo=rl.search(l)
                            nm=l.split(',')[-1].strip()
                            gn=g.group(1) if g else "GERAL"
                            cr={'name':nm,'group':gn,'logo':lo.group(1) if lo else "",'url':''}
                        elif not l.startswith('#') and cr:
                            cr['url']=l
                            batch.append((cr['name'], cr['group'], cr['logo'], cr['url']))
                            cr={}
                            cnt+=1
                            
                            if len(batch) >= 1000:
                                cc.executemany("INSERT INTO m3u_items (name, group_title, logo, url) VALUES (?,?,?,?)", batch)
                                conn_cache.commit()
                                batch = []
                                stt.info(f"Processando... {cnt} itens")
                    
                    if batch:
                        cc.executemany("INSERT INTO m3u_items (name, group_title, logo, url) VALUES (?,?,?,?)", batch)
                        conn_cache.commit()
                    
                    stt.success(f"Finalizado! {cnt} itens prontos.")
                    return True
            except Exception as e:
                st.error(f"Erro: {e}")
                return False
            finally:
                conn_cache.close()

        c1, c2 = st.columns([3,1])
        url = c1.text_input("URL M3U", disabled=st.session_state['step']>1)
        tp = c2.selectbox("Tipo", ["Live", "Movies", "Series"], disabled=st.session_state['step']>1)
        
        if st.session_state['step'] == 1:
            if st.button("ANALISAR M3U (MODO TURBO)"):
                if url:
                    if proc_to_disk(url):
                        st.session_state['step'] = 2
                        st.rerun()

        if st.session_state['step'] == 2:
            # Lê do Cache sem apagar
            conn_cache = sqlite3.connect(CACHE_FILE)
            cc = conn_cache.cursor()
            cc.execute("SELECT COUNT(*) FROM m3u_items")
            total_items = cc.fetchone()[0]
            cc.execute("SELECT DISTINCT group_title FROM m3u_items ORDER BY group_title")
            cats = [r[0] for r in cc.fetchall()]
            conn_cache.close()
            
            st.success(f"{total_items} itens carregados no Cache.")
            
            r1=st.columns(2)
            try:
                cur=conn.cursor(dictionary=True)
                cur.execute("SELECT id, server_name FROM streaming_servers")
                srvs=cur.fetchall()
                cur.execute("SELECT id, bouquet_name FROM bouquets")
                bqs=cur.fetchall()
                
                so={s['server_name']:s['id'] for s in srvs}
                sn=r1[0].selectbox("Servidor:",list(so.keys()) if so else [])
                sid=so.get(sn)
                
                bo={b['bouquet_name']:b['id'] for b in bqs}
                bn=r1[1].multiselect("Pacotes:",list(bo.keys()))
                bids=[bo[x] for x in bn]
                
                st.write("---")
                fc=st.columns(3)
                if fc[2].button("Voltar"):
                    st.session_state['step']=1
                    st.rerun()
                
                sc=st.multiselect("Categorias:", cats)
                
                if st.button("🚀 IMPORTAR", type="primary"):
                    if sc and sid:
                        conn_cache = sqlite3.connect(CACHE_FILE)
                        cc = conn_cache.cursor()
                        placeholders = ','.join('?' for _ in sc)
                        cc.execute(f"SELECT name, group_title, logo, url FROM m3u_items WHERE group_title IN ({placeholders})", sc)
                        items_to_import = cc.fetchall()
                        conn_cache.close()
                        
                        isr="Series" in tp
                        tid=5 if isr else (2 if "Movies" in tp else 1)
                        cdb="series" if isr else ("movie" if "Movies" in tp else "live")
                        tot=len(items_to_import)
                        pb=st.progress(0)
                        tx=st.empty()
                        cr=conn.cursor()
                        nid=[]
                        
                        for i, item in enumerate(items_to_import):
                            try:
                                cid=get_cid(cr,conn,item[1],cdb)
                                ts=int(datetime.now().timestamp())
                                cr.execute("INSERT INTO streams (type,category_id,stream_display_name,stream_source,stream_icon,direct_source,added,enable_transcode,read_native) VALUES (%s,%s,%s,%s,%s,1,%s,0,1)",(tid,cid,item[0],item[3],item[2],ts))
                                nid.append(cr.lastrowid)
                            except: pass
                            if i%50==0:
                                pb.progress((i+1)/tot)
                                tx.text(f"{i}/{tot}...")
                        
                        conn.commit()
                        lnk_srv(conn,nid,sid,bids,cdb)
                        pb.progress(1.0)
                        st.balloons()
                        st.success("Feito!")
                        time.sleep(2)
                        st.session_state['step']=1
                        st.rerun()
                    else: st.error("Selecione Servidor e Categoria")
            except: st.error("Erro ao ler servidor/bouquets")
    else: st.warning("Conexão necessária.")

# --- TAB 3: ADMIN ---
if curr_user == 'admin':
    with tabs[2]:
        st.subheader("Gerenciar Clientes")
        if st.session_state['view_mode']:
            vu = st.session_state['view_mode']
            vd = db_action("SELECT * FROM users WHERE username=?", (vu,))[0]
            base_url = config.get('base_url', f"http://{get_public_ip()}:7001")
            msg_zap = f"*DADOS DE ACESSO* 🚀%0A%0A🔗 Link: {base_url}%0A👤 User: {vd[0]}%0A🔑 Senha: {vd[1]}%0A📅 Vence: {vd[2]}"
            st.info(f"📤 Compartilhar: **{vu}**")
            st.markdown(f"""<div class="copy-box">🔗 Link: {base_url}<br>👤 User: {vd[0]}<br>🔑 Senha: {vd[1]}<br>📅 Vence: {vd[2]}</div>""", unsafe_allow_html=True)
            c1, c2 = st.columns(2)
            c1.markdown(f'<a href="https://wa.me/?text={msg_zap}" target="_blank"><button style="background:#25D366;color:white;border:none;padding:10px;border-radius:5px;width:100%;font-weight:bold;">📲 ENVIAR WHATSAPP</button></a>', unsafe_allow_html=True)
            if c2.button("Fechar"):
                st.session_state['view_mode']=None
                st.rerun()
            st.write("---")

        if st.session_state['edit_mode']:
            ue = st.session_state['edit_mode']
            ud = db_action("SELECT * FROM users WHERE username=?", (ue,))[0]
            st.info(f"✏️ Editando: {ue}")
            ec1, ec2 = st.columns(2)
            np = ec1.text_input("Nova Senha", value=ud[1])
            nd = ec2.date_input("Vencimento", value=datetime.strptime(ud[2], "%Y-%m-%d"))
            if st.button("💾 Salvar"):
                db_action("UPDATE users SET password=?, expire_date=? WHERE username=?", (np, nd, ue))
                st.success("Salvo!")
                st.session_state['edit_mode']=None
                time.sleep(1)
                st.rerun()
            if st.button("Cancelar"):
                st.session_state['edit_mode']=None
                st.rerun()
            st.write("---")

        with st.expander("➕ Criar Novo Cliente", expanded=True):
            cm = st.radio("Modo:", ["🎲 Gerar", "✍️ Manual"], horizontal=True)
            c1, c2, c3 = st.columns(3)
            if cm == "🎲 Gerar":
                nu = "cliente_" + generate_code(4)
                np = generate_code(6)
                st.caption(f"Prévia: {nu} / {np}")
            else:
                nu = c1.text_input("Usuário")
                np = c2.text_input("Senha")
            da = c3.number_input("Dias", value=30, min_value=1)
            if st.button("CRIAR"):
                if cm=="✍️ Manual" and (not nu or not np):
                    st.error("Preencha tudo")
                else:
                    exp = (datetime.now() + timedelta(days=da)).strftime("%Y-%m-%d")
                    try:
                        db_action("INSERT INTO users (username, password, expire_date, target_host, target_db, target_user, target_pass) VALUES (?, ?, ?, '', '', '', '')", (nu, np, exp))
                        st.session_state['view_mode'] = nu
                        st.rerun()
                    except: st.error("Usuário já existe")

        st.write("### 📋 Clientes")
        usrs = db_action("SELECT username, expire_date FROM users")
        if usrs:
            for u in usrs:
                if u[0] == 'admin': continue
                c1, c2, c3, c4, c5 = st.columns([3, 2, 1, 1, 1])
                c1.write(f"👤 **{u[0]}**")
                c2.write(f"📅 {u[1]}")
                if c3.button("📲", key=f"sh_{u[0]}"):
                    st.session_state['view_mode'] = u[0]
                    st.rerun()
                if c4.button("✏️", key=f"ed_{u[0]}"):
                    st.session_state['edit_mode'] = u[0]
                    st.rerun()
                if c5.button("🗑️", key=f"dl_{u[0]}"):
                    db_action("DELETE FROM users WHERE username=?", (u[0],))
                    st.rerun()
                st.markdown("<hr style='margin:5px 0; border-color: #334155'>", unsafe_allow_html=True)
EOF

# 3. Reinicia
sudo ufw allow 7001/tcp > /dev/null 2>&1
nohup streamlit run importer.py --server.port 7001 --server.address 0.0.0.0 > output.log 2>&1 &
