"""
auth.py - Gerenciamento de usuários, contas e config GHL via SQLite + Flask-Login
"""

import sqlite3
from datetime import datetime
from pathlib import Path
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin

DB_PATH = Path("/opt/mia/workspace/prospeccao_ativa/users.db")

SUPER_ADMIN_EMAIL = "remoraes09@gmail.com"
SUPER_ADMIN_SENHA = "Climb@2026"
SUPER_ADMIN_NOME = "Renato Moraes"


def _get_conn():
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row
    return conn


def init_db():
    conn = _get_conn()

    # Contas (clientes)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS contas (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            nome TEXT NOT NULL,
            criado_em TEXT NOT NULL
        )
    """)

    # Usuários
    conn.execute("""
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            nome TEXT NOT NULL,
            email TEXT UNIQUE NOT NULL,
            password_hash TEXT NOT NULL,
            plano TEXT NOT NULL DEFAULT 'beta',
            conta_id INTEGER REFERENCES contas(id) ON DELETE SET NULL,
            ativo INTEGER NOT NULL DEFAULT 1,
            criado_em TEXT NOT NULL,
            ultimo_acesso TEXT
        )
    """)

    # Migração: adiciona conta_id se coluna não existe ainda
    try:
        conn.execute("ALTER TABLE users ADD COLUMN conta_id INTEGER REFERENCES contas(id) ON DELETE SET NULL")
        conn.commit()
    except Exception:
        pass

    # Config GHL por conta
    conn.execute("""
        CREATE TABLE IF NOT EXISTS ghl_config (
            conta_id INTEGER PRIMARY KEY REFERENCES contas(id) ON DELETE CASCADE,
            crm_type TEXT NOT NULL DEFAULT 'ghl',
            token TEXT NOT NULL DEFAULT '',
            location_id TEXT NOT NULL DEFAULT '',
            pipeline_id TEXT NOT NULL DEFAULT '',
            stage_id TEXT NOT NULL DEFAULT '',
            location_name TEXT NOT NULL DEFAULT '',
            pipeline_name TEXT NOT NULL DEFAULT '',
            stage_name TEXT NOT NULL DEFAULT '',
            atualizado_em TEXT,
            leads_limite INTEGER NOT NULL DEFAULT 1000,
            leads_usados INTEGER NOT NULL DEFAULT 0,
            quota_reset_em TEXT
        )
    """)
    conn.commit()

    # Migração: adiciona campos de quota se ainda não existirem
    for ddl in (
        "ALTER TABLE ghl_config ADD COLUMN leads_limite INTEGER NOT NULL DEFAULT 1000",
        "ALTER TABLE ghl_config ADD COLUMN leads_usados INTEGER NOT NULL DEFAULT 0",
        "ALTER TABLE ghl_config ADD COLUMN quota_reset_em TEXT",
    ):
        try:
            conn.execute(ddl)
            conn.commit()
        except Exception:
            pass

    # Seed super_admin
    cursor = conn.execute("SELECT COUNT(*) FROM users WHERE plano = 'super_admin'")
    if cursor.fetchone()[0] == 0:
        conn.execute("""
            INSERT INTO users (nome, email, password_hash, plano, ativo, criado_em)
            VALUES (?, ?, ?, 'super_admin', 1, ?)
        """, (SUPER_ADMIN_NOME, SUPER_ADMIN_EMAIL,
              generate_password_hash(SUPER_ADMIN_SENHA), datetime.now().isoformat()))
        conn.commit()
        print(f"[auth] Seed: super_admin criado ({SUPER_ADMIN_EMAIL})")

    conn.close()


# ── CONTAS ──────────────────────────────────────────────

def criar_conta(nome: str) -> dict:
    conn = _get_conn()
    cur = conn.execute(
        "INSERT INTO contas (nome, criado_em) VALUES (?, ?)",
        (nome.strip(), datetime.now().isoformat())
    )
    conn.commit()
    conta_id = cur.lastrowid
    row = conn.execute("SELECT * FROM contas WHERE id = ?", (conta_id,)).fetchone()
    conn.close()
    return dict(row)


def listar_contas() -> list:
    conn = _get_conn()
    rows = conn.execute("SELECT * FROM contas ORDER BY nome").fetchall()
    conn.close()
    return [dict(r) for r in rows]


def get_conta(conta_id: int) -> dict | None:
    conn = _get_conn()
    row = conn.execute("SELECT * FROM contas WHERE id = ?", (conta_id,)).fetchone()
    conn.close()
    return dict(row) if row else None


def deletar_conta(conta_id: int) -> bool:
    conn = _get_conn()
    conn.execute("DELETE FROM contas WHERE id = ?", (conta_id,))
    conn.commit()
    conn.close()
    return True


def renomear_conta(conta_id: int, nome: str) -> bool:
    conn = _get_conn()
    conn.execute("UPDATE contas SET nome = ? WHERE id = ?", (nome.strip(), conta_id))
    conn.commit()
    conn.close()
    return True


# ── GHL CONFIG POR CONTA ─────────────────────────────────

def get_ghl_config(conta_id: int) -> dict | None:
    conn = _get_conn()
    row = conn.execute("SELECT * FROM ghl_config WHERE conta_id = ?", (conta_id,)).fetchone()
    conn.close()
    if not row or not row["token"]:
        return None
    return dict(row)


def save_ghl_config(conta_id: int, crm_type: str, token: str, location_id: str,
                    pipeline_id: str, stage_id: str,
                    location_name: str, pipeline_name: str, stage_name: str) -> None:
    conn = _get_conn()
    conn.execute("""
        INSERT INTO ghl_config (conta_id, crm_type, token, location_id, pipeline_id, stage_id,
                                location_name, pipeline_name, stage_name, atualizado_em)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        ON CONFLICT(conta_id) DO UPDATE SET
            crm_type=excluded.crm_type, token=excluded.token,
            location_id=excluded.location_id, pipeline_id=excluded.pipeline_id,
            stage_id=excluded.stage_id, location_name=excluded.location_name,
            pipeline_name=excluded.pipeline_name, stage_name=excluded.stage_name,
            atualizado_em=excluded.atualizado_em
    """, (conta_id, crm_type, token, location_id, pipeline_id, stage_id,
          location_name, pipeline_name, stage_name, datetime.now().isoformat()))
    conn.commit()
    conn.close()


# ── QUOTA DE LEADS POR CONTA ─────────────────────────────

def _garantir_linha_quota(conn, conta_id: int):
    """Garante que existe uma linha em ghl_config para a conta (com defaults de quota)."""
    row = conn.execute(
        "SELECT conta_id FROM ghl_config WHERE conta_id = ?", (conta_id,)
    ).fetchone()
    if not row:
        conn.execute("""
            INSERT INTO ghl_config (conta_id, leads_limite, leads_usados, quota_reset_em)
            VALUES (?, 1000, 0, ?)
        """, (conta_id, datetime.now().isoformat()))
        conn.commit()


def get_quota(conta_id: int) -> dict:
    """Retorna {limite, usados, disponivel, reset_em} para a conta."""
    conn = _get_conn()
    _garantir_linha_quota(conn, conta_id)
    row = conn.execute(
        "SELECT leads_limite, leads_usados, quota_reset_em FROM ghl_config WHERE conta_id = ?",
        (conta_id,)
    ).fetchone()
    conn.close()
    if not row:
        return {"limite": 1000, "usados": 0, "disponivel": 1000, "reset_em": None}
    limite = int(row["leads_limite"] or 0)
    usados = int(row["leads_usados"] or 0)
    return {
        "limite": limite,
        "usados": usados,
        "disponivel": max(0, limite - usados),
        "reset_em": row["quota_reset_em"],
    }


def incrementar_quota(conta_id: int, quantidade: int) -> dict:
    """Soma 'quantidade' ao contador de leads usados da conta."""
    if quantidade <= 0:
        return get_quota(conta_id)
    conn = _get_conn()
    _garantir_linha_quota(conn, conta_id)
    conn.execute(
        "UPDATE ghl_config SET leads_usados = leads_usados + ? WHERE conta_id = ?",
        (int(quantidade), conta_id)
    )
    conn.commit()
    conn.close()
    return get_quota(conta_id)


def resetar_quota_se_novo_mes(conta_id: int) -> dict:
    """Zera leads_usados se quota_reset_em estiver em mês anterior ao atual."""
    conn = _get_conn()
    _garantir_linha_quota(conn, conta_id)
    row = conn.execute(
        "SELECT quota_reset_em FROM ghl_config WHERE conta_id = ?", (conta_id,)
    ).fetchone()

    agora = datetime.now()
    precisa_resetar = False
    reset_em_atual = row["quota_reset_em"] if row else None

    if not reset_em_atual:
        precisa_resetar = True
    else:
        try:
            ult = datetime.fromisoformat(reset_em_atual)
            if (ult.year, ult.month) != (agora.year, agora.month):
                precisa_resetar = True
        except Exception:
            precisa_resetar = True

    if precisa_resetar:
        novo_reset = datetime(agora.year, agora.month, 1).isoformat()
        conn.execute(
            "UPDATE ghl_config SET leads_usados = 0, quota_reset_em = ? WHERE conta_id = ?",
            (novo_reset, conta_id)
        )
        conn.commit()
    conn.close()
    return get_quota(conta_id)


# ── USUÁRIOS ─────────────────────────────────────────────

class User(UserMixin):
    def __init__(self, row):
        self.id = str(row["id"])
        self.nome = row["nome"]
        self.email = row["email"]
        self.password_hash = row["password_hash"]
        self.plano = row["plano"]
        self.conta_id = row["conta_id"]
        self.ativo = bool(row["ativo"])
        self.criado_em = row["criado_em"]
        self.ultimo_acesso = row["ultimo_acesso"]

    @property
    def is_super_admin(self):
        return self.plano == "super_admin"

    @property
    def is_conta_admin(self):
        return self.plano in ("super_admin", "conta_admin")

    @staticmethod
    def get(user_id):
        conn = _get_conn()
        row = conn.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone()
        conn.close()
        return User(row) if row else None

    def is_active(self):
        return self.ativo


def buscar_por_email(email: str):
    conn = _get_conn()
    row = conn.execute("SELECT * FROM users WHERE email = ?", (email.strip().lower(),)).fetchone()
    conn.close()
    return User(row) if row else None


def criar_usuario(nome: str, email: str, senha: str,
                  plano: str = "beta", conta_id: int = None) -> tuple:
    email = email.strip().lower()
    if buscar_por_email(email):
        return None, "E-mail já cadastrado."
    if not nome or not email or not senha:
        return None, "Nome, e-mail e senha são obrigatórios."
    try:
        conn = _get_conn()
        conn.execute("""
            INSERT INTO users (nome, email, password_hash, plano, conta_id, ativo, criado_em)
            VALUES (?, ?, ?, ?, ?, 1, ?)
        """, (nome.strip(), email, generate_password_hash(senha),
              plano, conta_id, datetime.now().isoformat()))
        conn.commit()
        conn.close()
        return buscar_por_email(email), None
    except Exception as e:
        return None, str(e)


def listar_usuarios(conta_id: int = None) -> list:
    conn = _get_conn()
    if conta_id is not None:
        rows = conn.execute(
            "SELECT * FROM users WHERE conta_id = ? ORDER BY criado_em DESC", (conta_id,)
        ).fetchall()
    else:
        rows = conn.execute("SELECT * FROM users ORDER BY criado_em DESC").fetchall()
    conn.close()
    return [User(r) for r in rows]


def atualizar_usuario(user_id: int, **kwargs) -> bool:
    campos_permitidos = {"nome", "email", "plano", "ativo", "ultimo_acesso", "conta_id"}
    updates = {k: v for k, v in kwargs.items() if k in campos_permitidos}
    if not updates:
        return False
    set_clause = ", ".join(f"{k} = ?" for k in updates)
    values = list(updates.values()) + [user_id]
    conn = _get_conn()
    conn.execute(f"UPDATE users SET {set_clause} WHERE id = ?", values)
    conn.commit()
    conn.close()
    return True


def deletar_usuario(user_id: int) -> bool:
    conn = _get_conn()
    conn.execute("DELETE FROM users WHERE id = ?", (user_id,))
    conn.commit()
    conn.close()
    return True


def verificar_senha(user: User, senha: str) -> bool:
    return check_password_hash(user.password_hash, senha)


def registrar_acesso(user_id: int):
    atualizar_usuario(user_id, ultimo_acesso=datetime.now().isoformat())
