'use strict'

/**
 * database.js — Camada de compatibilidade PostgreSQL
 *
 * Mantém a mesma API do módulo sql.js anterior (runQuery/getOne/getAll/saveDatabase)
 * para que os controllers e plugins existentes não precisem ser alterados.
 *
 * As funções agora são ASSÍNCRONAS internamente mas retornam Promises,
 * e o server.js chama initialize() com await antes de iniciar.
 */

const { execute, queryOne, query } = require('./postgres')

// Compatibilidade: controllers antigos usam runQuery/getOne/getAll de forma síncrona
// via require('../database/database'). Como o Express suporta async handlers,
// os controllers foram atualizados para async/await nos models.
// Este arquivo apenas exporta os helpers para código legado restante (plugins).

async function initialize() {
  const row = await queryOne('SELECT NOW() as now')
  console.log('✅ PostgreSQL conectado:', row.now)

  // Fase 7: colunas idempotentes
  await execute(`ALTER TABLE users    ADD COLUMN IF NOT EXISTS whatsapp_optin       BOOLEAN DEFAULT TRUE`)
  await execute(`ALTER TABLE raffles  ADD COLUMN IF NOT EXISTS last_hours_notif_sent TIMESTAMPTZ`)
  await execute(`ALTER TABLE raffle_claims ADD COLUMN IF NOT EXISTS notified_at TIMESTAMPTZ`)
  console.log('✅ Colunas Fase 7 verificadas')

  // ── Fase 9B — Auth email + senha ──────────────────────────────────────────
  await execute(`ALTER TABLE users ADD COLUMN IF NOT EXISTS password_hash VARCHAR(255)`)
  await execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email_tenant ON users(email, tenant_id) WHERE email IS NOT NULL`)

  await execute(`
    CREATE TABLE IF NOT EXISTS password_reset_tokens (
      id         SERIAL PRIMARY KEY,
      user_id    INT          NOT NULL REFERENCES users(id) ON DELETE CASCADE,
      token      VARCHAR(128) NOT NULL UNIQUE,
      expires_at TIMESTAMPTZ  NOT NULL,
      used       BOOLEAN      NOT NULL DEFAULT FALSE,
      created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_prt_token ON password_reset_tokens(token)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_prt_user  ON password_reset_tokens(user_id)`)
  console.log('✅ Fase 9B — Auth email+senha verificada')

  // ── Fase 9A — Multi-tenant ─────────────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS tenants (
      id         SERIAL PRIMARY KEY,
      slug       VARCHAR(80)  NOT NULL UNIQUE,
      name       VARCHAR(255) NOT NULL,
      domain     VARCHAR(255),
      active     BOOLEAN      NOT NULL DEFAULT TRUE,
      created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)

  await execute(`
    CREATE TABLE IF NOT EXISTS tenant_config (
      tenant_id       INT          NOT NULL PRIMARY KEY REFERENCES tenants(id) ON DELETE CASCADE,
      primary_color   VARCHAR(20)  NOT NULL DEFAULT '#f59e0b',
      secondary_color VARCHAR(20)  NOT NULL DEFAULT '#10b981',
      logo_url        TEXT,
      favicon_url     TEXT,
      contact_email   VARCHAR(255),
      contact_phone   VARCHAR(30),
      app_url         VARCHAR(255),
      asaas_key       VARCHAR(255)
    )
  `)

  // Tenant padrão — Alemão Conveniências
  await execute(`
    INSERT INTO tenants (id, slug, name, domain, active)
    VALUES (1, 'alemao', 'Alemão Conveniências', 'alemaoconveniencias.local', true)
    ON CONFLICT (id) DO NOTHING
  `)
  await execute(`
    INSERT INTO tenant_config (tenant_id, primary_color, secondary_color, app_url)
    VALUES (1, '#f59e0b', '#10b981', 'http://alemaoconveniencias.local:4001')
    ON CONFLICT (tenant_id) DO NOTHING
  `)

  // tenant_id nas tabelas existentes
  await execute(`ALTER TABLE users       ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)
  await execute(`ALTER TABLE raffles     ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)
  await execute(`ALTER TABLE orders      ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)
  await execute(`ALTER TABLE tickets     ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)
  await execute(`ALTER TABLE promotions  ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)
  await execute(`ALTER TABLE whatsapp_logs ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)

  // Popular registros existentes sem tenant_id
  await execute(`UPDATE users        SET tenant_id = 1 WHERE tenant_id IS NULL`)
  await execute(`UPDATE raffles      SET tenant_id = 1 WHERE tenant_id IS NULL`)
  await execute(`UPDATE orders       SET tenant_id = 1 WHERE tenant_id IS NULL`)
  await execute(`UPDATE tickets      SET tenant_id = 1 WHERE tenant_id IS NULL`)
  await execute(`UPDATE promotions   SET tenant_id = 1 WHERE tenant_id IS NULL`)
  await execute(`UPDATE whatsapp_logs SET tenant_id = 1 WHERE tenant_id IS NULL`)

  // Índices de performance
  await execute(`CREATE INDEX IF NOT EXISTS idx_users_tenant       ON users(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_raffles_tenant     ON raffles(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_orders_tenant      ON orders(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_tickets_tenant     ON tickets(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_promotions_tenant  ON promotions(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_wa_logs_tenant     ON whatsapp_logs(tenant_id)`)

  // ── Fase 10A — Clube de Benefícios (tabelas com tenant_id desde o início) ──
  await execute(`
    CREATE TABLE IF NOT EXISTS benefit_clubs (
      id         SERIAL PRIMARY KEY,
      tenant_id  INT          NOT NULL REFERENCES tenants(id),
      slug       VARCHAR(80)  NOT NULL,
      name       VARCHAR(255) NOT NULL,
      specialty  VARCHAR(80)  NOT NULL DEFAULT 'outro',
      active     BOOLEAN      NOT NULL DEFAULT TRUE,
      created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      UNIQUE(tenant_id, slug)
    )
  `)

  await execute(`
    CREATE TABLE IF NOT EXISTS club_plans (
      id             SERIAL PRIMARY KEY,
      club_id        INT            NOT NULL REFERENCES benefit_clubs(id),
      name           VARCHAR(255)   NOT NULL,
      description    TEXT,
      price_monthly  NUMERIC(10,2)  NOT NULL,
      max_dependents INT            NOT NULL DEFAULT 0,
      features       JSONB          NOT NULL DEFAULT '[]',
      active         BOOLEAN        NOT NULL DEFAULT TRUE,
      created_at     TIMESTAMPTZ    NOT NULL DEFAULT NOW()
    )
  `)

  await execute(`
    CREATE TABLE IF NOT EXISTS club_members (
      id                     SERIAL PRIMARY KEY,
      tenant_id              INT          NOT NULL REFERENCES tenants(id),
      club_id                INT          NOT NULL REFERENCES benefit_clubs(id),
      plan_id                INT          NOT NULL REFERENCES club_plans(id),
      user_cpf               VARCHAR(14)  NOT NULL,
      user_nome              VARCHAR(255) NOT NULL,
      user_telefone          VARCHAR(20),
      user_email             VARCHAR(255),
      status                 VARCHAR(20)  NOT NULL DEFAULT 'pending_payment',
      asaas_subscription_id  VARCHAR(255),
      asaas_customer_id      VARCHAR(255),
      next_billing_at        DATE,
      started_at             TIMESTAMPTZ,
      canceled_at            TIMESTAMPTZ,
      created_at             TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_club_members_cpf    ON club_members(user_cpf)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_club_members_tenant  ON club_members(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_club_members_status  ON club_members(status)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS club_dependents (
      id          SERIAL PRIMARY KEY,
      member_id   INT          NOT NULL REFERENCES club_members(id) ON DELETE CASCADE,
      nome        VARCHAR(255) NOT NULL,
      cpf         VARCHAR(14),
      nascimento  DATE,
      parentesco  VARCHAR(80),
      created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)

  await execute(`
    CREATE TABLE IF NOT EXISTS club_payments (
      id               SERIAL PRIMARY KEY,
      member_id        INT           NOT NULL REFERENCES club_members(id),
      plan_id          INT           NOT NULL REFERENCES club_plans(id),
      amount           NUMERIC(10,2) NOT NULL,
      status           VARCHAR(20)   NOT NULL DEFAULT 'pending',
      asaas_payment_id VARCHAR(255),
      reference_month  VARCHAR(7),
      paid_at          TIMESTAMPTZ,
      created_at       TIMESTAMPTZ   NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_club_payments_member ON club_payments(member_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_club_payments_status ON club_payments(status)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS club_partners (
      id               SERIAL PRIMARY KEY,
      club_id          INT          NOT NULL REFERENCES benefit_clubs(id),
      tenant_id        INT          REFERENCES tenants(id),
      name             VARCHAR(255) NOT NULL,
      specialty        VARCHAR(255),
      phone            VARCHAR(20),
      address          TEXT,
      discount_percent INT          NOT NULL DEFAULT 0,
      notes            TEXT,
      active           BOOLEAN      NOT NULL DEFAULT TRUE,
      created_at       TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  // Migração: renomear colunas PT → EN (idempotente via DO $$)
  await execute(`
    DO $$ BEGIN
      IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='club_partners' AND column_name='nome') THEN
        ALTER TABLE club_partners RENAME COLUMN nome        TO name;
        ALTER TABLE club_partners RENAME COLUMN especialidade TO specialty;
        ALTER TABLE club_partners RENAME COLUMN telefone    TO phone;
        ALTER TABLE club_partners RENAME COLUMN endereco    TO address;
        ALTER TABLE club_partners RENAME COLUMN desconto_percent TO discount_percent;
        ALTER TABLE club_partners RENAME COLUMN ativo       TO active;
      END IF;
    END $$
  `)
  await execute(`ALTER TABLE club_partners ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)
  await execute(`ALTER TABLE club_partners ADD COLUMN IF NOT EXISTS notes     TEXT`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_club_partners_club ON club_partners(club_id)`)

  // Dados iniciais — clubes e planos do Alemão
  await execute(`
    INSERT INTO benefit_clubs (tenant_id, slug, name, specialty, active)
    VALUES
      (1, 'odonto', 'Clube Odonto', 'odonto', true),
      (1, 'medico', 'Clube Médico', 'medico', true)
    ON CONFLICT (tenant_id, slug) DO NOTHING
  `)

  const odonto = await queryOne(`SELECT id FROM benefit_clubs WHERE tenant_id=1 AND slug='odonto'`)
  const medico = await queryOne(`SELECT id FROM benefit_clubs WHERE tenant_id=1 AND slug='medico'`)

  if (odonto) {
    const existing = await queryOne(`SELECT id FROM club_plans WHERE club_id = $1 LIMIT 1`, [odonto.id])
    if (!existing) {
      await execute(
        `INSERT INTO club_plans (club_id, name, description, price_monthly, max_dependents, features) VALUES
          ($1, 'Individual', 'Plano para uma pessoa', 25.00, 0, $2),
          ($1, 'Família', 'Plano para até 4 dependentes', 80.00, 4, $3)`,
        [
          odonto.id,
          JSON.stringify(['Limpezas e Prevenção','Descontos em Tratamentos','Extrações e Obturações','Sem Carência']),
          JSON.stringify(['Até 4 Dependentes','Limpezas e Prevenção','Descontos em Tratamentos','Urgência e Emergência']),
        ]
      )
    }
  }

  if (medico) {
    const existing = await queryOne(`SELECT id FROM club_plans WHERE club_id = $1 LIMIT 1`, [medico.id])
    if (!existing) {
      await execute(
        `INSERT INTO club_plans (club_id, name, description, price_monthly, max_dependents, features) VALUES
          ($1, 'Individual', 'Plano médico individual', 35.00, 0, $2),
          ($1, 'Família', 'Plano médico familiar', 99.00, 4, $3)`,
        [
          medico.id,
          JSON.stringify(['Consultas com Clínico Geral','Descontos em Exames','Pediatria','Sem Carência']),
          JSON.stringify(['Até 4 Dependentes','Clínico Geral e Especialistas','Descontos em Exames','Urgência e Emergência']),
        ]
      )
    }
  }

  // ── Fase 10B — Condições, Regras e FAQ por clube ──────────────────────────
  await execute(`ALTER TABLE benefit_clubs ADD COLUMN IF NOT EXISTS conditions TEXT`)
  await execute(`ALTER TABLE benefit_clubs ADD COLUMN IF NOT EXISTS rules      TEXT`)

  await execute(`
    CREATE TABLE IF NOT EXISTS club_faqs (
      id         SERIAL PRIMARY KEY,
      club_id    INT          NOT NULL REFERENCES benefit_clubs(id) ON DELETE CASCADE,
      tenant_id  INT          NOT NULL REFERENCES tenants(id),
      question   TEXT         NOT NULL,
      answer     TEXT         NOT NULL,
      sort_order INT          NOT NULL DEFAULT 0,
      active     BOOLEAN      NOT NULL DEFAULT true,
      created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_club_faqs_club ON club_faqs(club_id)`)

  // Seed das FAQs padrão por clube (apenas se ainda não houver nenhuma)
  if (odonto) {
    const faqExists = await queryOne(`SELECT id FROM club_faqs WHERE club_id=$1 LIMIT 1`, [odonto.id])
    if (!faqExists) {
      await execute(
        `INSERT INTO club_faqs (club_id, tenant_id, question, answer, sort_order) VALUES
          ($1, 1, 'Como funciona o pagamento?', 'O pagamento é mensal via PIX, gerado automaticamente. Você recebe o link no WhatsApp antes do vencimento.', 0),
          ($1, 1, 'Posso cancelar a qualquer momento?', 'Sim. Acesse sua área do cliente e solicite o cancelamento. O plano permanece ativo até o fim do período pago.', 1),
          ($1, 1, 'Meus dependentes têm acesso?', 'Sim, dependendo do plano escolhido. O plano Família inclui cobertura para até 4 dependentes.', 2),
          ($1, 1, 'Como acessar as clínicas parceiras?', 'Apresente sua carteirinha digital (acessível pela área do cliente) na recepção da clínica parceira.', 3)`,
        [odonto.id]
      )
    }
  }
  if (medico) {
    const faqExists = await queryOne(`SELECT id FROM club_faqs WHERE club_id=$1 LIMIT 1`, [medico.id])
    if (!faqExists) {
      await execute(
        `INSERT INTO club_faqs (club_id, tenant_id, question, answer, sort_order) VALUES
          ($1, 1, 'Como funciona o pagamento?', 'O pagamento é mensal via PIX, gerado automaticamente. Você recebe o link no WhatsApp antes do vencimento.', 0),
          ($1, 1, 'Posso cancelar a qualquer momento?', 'Sim. Acesse sua área do cliente e solicite o cancelamento. O plano permanece ativo até o fim do período pago.', 1),
          ($1, 1, 'Meus dependentes têm acesso?', 'Sim, dependendo do plano escolhido. O plano Família inclui cobertura para até 4 dependentes.', 2),
          ($1, 1, 'Como acessar as clínicas parceiras?', 'Apresente sua carteirinha digital (acessível pela área do cliente) na recepção da clínica parceira.', 3)`,
        [medico.id]
      )
    }
  }
  console.log('✅ Fase 10B — club_faqs e colunas conditions/rules verificadas')

  console.log('✅ Fase 9A — Multi-tenant e tabelas do Clube criadas/verificadas')

  // ── Fase 11 — Banco de Talentos ──────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS jobs (
      id           SERIAL PRIMARY KEY,
      tenant_id    INT           NOT NULL REFERENCES tenants(id),
      title        TEXT          NOT NULL,
      description  TEXT          NOT NULL,
      requirements TEXT,
      benefits     TEXT,
      location     TEXT,
      work_mode    TEXT          NOT NULL DEFAULT 'presencial',
      job_type     TEXT          NOT NULL DEFAULT 'clt',
      category     TEXT,
      salary_min   NUMERIC(10,2),
      salary_max   NUMERIC(10,2),
      salary_hide  BOOLEAN       NOT NULL DEFAULT false,
      slots        INT           NOT NULL DEFAULT 1,
      active       BOOLEAN       NOT NULL DEFAULT true,
      published_at TIMESTAMPTZ   DEFAULT NOW(),
      expires_at   TIMESTAMPTZ,
      created_at   TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
      updated_at   TIMESTAMPTZ   NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_jobs_tenant    ON jobs(tenant_id, active)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_jobs_published ON jobs(published_at DESC)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS resumes (
      id         SERIAL PRIMARY KEY,
      tenant_id  INT         NOT NULL REFERENCES tenants(id),
      user_cpf   TEXT        NOT NULL,
      user_nome  TEXT        NOT NULL,
      email      TEXT,
      phone      TEXT,
      linkedin   TEXT,
      portfolio  TEXT,
      about      TEXT,
      experience JSONB       NOT NULL DEFAULT '[]',
      education  JSONB       NOT NULL DEFAULT '[]',
      skills     JSONB       NOT NULL DEFAULT '[]',
      file_url   TEXT,
      updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      UNIQUE (tenant_id, user_cpf)
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_resumes_cpf ON resumes(tenant_id, user_cpf)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS job_applications (
      id              SERIAL PRIMARY KEY,
      tenant_id       INT         NOT NULL REFERENCES tenants(id),
      job_id          INT         NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
      resume_id       INT         REFERENCES resumes(id),
      applicant_nome  TEXT        NOT NULL,
      applicant_email TEXT,
      applicant_phone TEXT,
      applicant_cpf   TEXT        NOT NULL,
      cover_letter    TEXT,
      status          TEXT        NOT NULL DEFAULT 'novo',
      admin_notes     TEXT,
      applied_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      updated_at      TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      UNIQUE (job_id, applicant_cpf)
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_applications_job ON job_applications(job_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_applications_cpf ON job_applications(applicant_cpf)`)
  console.log('✅ Fase 11 — Banco de Talentos verificado')

  // ── Fase 9F — Admin tenant_id ────────────────────────────────────────────
  await execute(`ALTER TABLE admins ADD COLUMN IF NOT EXISTS tenant_id INT REFERENCES tenants(id)`)
  // Associa admins existentes sem tenant ao tenant padrão (alemao = 1)
  await execute(`UPDATE admins SET tenant_id=1 WHERE tenant_id IS NULL`)
  console.log('✅ Fase 9F — tenant_id em admins verificado')

  // ── Admin ↔ Account link ──────────────────────────────────────────────────
  // Motivo: o admin (tabela `admins`) e o colaborador (tabela `accounts`) são
  // entidades separadas com JWTs distintos. Sem essa ligação, quando o admin
  // está logado pela sessão admin, a Inbox Interna não sabe qual account usar
  // como identidade — e exibe "login de colaborador necessário".
  // Solução: um campo account_id opcional em admins. Quando preenchido, o
  // endpoint /api/admin/me devolve o account_id e o frontend usa esse valor
  // diretamente na Inbox Interna, sem exigir um segundo login.
  await execute(`ALTER TABLE admins ADD COLUMN IF NOT EXISTS account_id INT REFERENCES accounts(id) ON DELETE SET NULL`)
  console.log('✅ Admin ↔ Account link: coluna account_id adicionada em admins')

  // ── Fase 9E — Super Admin ─────────────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS super_admins (
      id            SERIAL PRIMARY KEY,
      email         VARCHAR(255) NOT NULL UNIQUE,
      password_hash VARCHAR(255) NOT NULL,
      name          VARCHAR(255) NOT NULL,
      created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  // Seed super admin padrão se não existir
  const bcrypt = require('bcryptjs')
  const existingSA = await queryOne('SELECT id FROM super_admins LIMIT 1')
  if (!existingSA) {
    const hash = await bcrypt.hash(process.env.SUPER_ADMIN_PASSWORD || 'superadmin123', 10)
    await execute(
      `INSERT INTO super_admins (email, password_hash, name) VALUES ($1,$2,$3)`,
      [process.env.SUPER_ADMIN_EMAIL || 'super@admin.local', hash, 'Super Admin']
    )
    console.log('✅ Super admin padrão criado — altere a senha em produção!')
  }
  console.log('✅ Fase 9E — Super Admin verificado')

  // ── Plugin NewWhats — tabela de eventos de inbox ──────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS nw_event_logs (
      id           SERIAL PRIMARY KEY,
      instance_id  VARCHAR(128)  NOT NULL DEFAULT '',
      event        VARCHAR(64)   NOT NULL,
      direction    VARCHAR(8)    NOT NULL DEFAULT 'in',
      chat_id      VARCHAR(128),
      from_me      BOOLEAN       NOT NULL DEFAULT FALSE,
      msg_type     VARCHAR(32),
      payload      JSONB,
      created_at   TIMESTAMPTZ   NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_event_logs_instance ON nw_event_logs(instance_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_event_logs_event    ON nw_event_logs(event)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_event_logs_created  ON nw_event_logs(created_at DESC)`)
  console.log('✅ Plugin NewWhats — tabela nw_event_logs verificada')

  // ── Plugin NewWhats — respostas automáticas da IA ─────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS nw_auto_replies (
      id          SERIAL PRIMARY KEY,
      instance_id VARCHAR(128)  NOT NULL,
      chat_id     VARCHAR(256)  NOT NULL,
      conv_id     VARCHAR(64),
      user_msg    TEXT,
      reply       TEXT,
      status      VARCHAR(20)   NOT NULL DEFAULT 'sent',
      created_at  TIMESTAMPTZ   NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_auto_chat     ON nw_auto_replies(chat_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_auto_instance ON nw_auto_replies(instance_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_auto_created  ON nw_auto_replies(created_at DESC)`)
  console.log('✅ Plugin NewWhats — tabela nw_auto_replies verificada')

  // Multi-tenant: adiciona tenant_id nas tabelas nw_ (retroativo com DEFAULT 1)
  await execute(`ALTER TABLE nw_event_logs  ADD COLUMN IF NOT EXISTS tenant_id INT NOT NULL DEFAULT 1`)
  await execute(`ALTER TABLE nw_auto_replies ADD COLUMN IF NOT EXISTS tenant_id INT NOT NULL DEFAULT 1`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_event_tenant  ON nw_event_logs(tenant_id, created_at DESC)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_auto_tenant   ON nw_auto_replies(tenant_id, created_at DESC)`)

  // ── Handoff local — pausa da IA por chat ──────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS nw_handoff (
      chat_id     TEXT        NOT NULL,
      tenant_id   INT         NOT NULL,
      human_until TIMESTAMPTZ,
      updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      PRIMARY KEY (chat_id, tenant_id)
    )
  `)
  console.log('✅ Plugin NewWhats — tabela nw_handoff verificada')

  // ── Setor identificado por chat ────────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS nw_chat_sectors (
      chat_id    TEXT        NOT NULL,
      tenant_id  INT         NOT NULL,
      sector_id  INT         REFERENCES sectors(id) ON DELETE SET NULL,
      updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      PRIMARY KEY (chat_id, tenant_id)
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_nw_chat_sectors_sector ON nw_chat_sectors(sector_id)`)

  // ── Avaliação de atendimento pelo cliente ──────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS protocol_ratings (
      id         SERIAL PRIMARY KEY,
      tenant_id  INT         NOT NULL REFERENCES tenants(id),
      thread_id  VARCHAR(64) NOT NULL,
      chat_id    TEXT        NOT NULL,
      account_id INT         REFERENCES accounts(id) ON DELETE SET NULL,
      rating     SMALLINT    CHECK (rating BETWEEN 1 AND 5),
      status     VARCHAR(20) NOT NULL DEFAULT 'pending'
                   CHECK (status IN ('pending','rated','expired')),
      sent_at    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      rated_at   TIMESTAMPTZ
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_protocol_ratings_tenant ON protocol_ratings(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_protocol_ratings_chat   ON protocol_ratings(chat_id)`)

  // ── Flags de protocolo (reclamação, sugestão, elogio) ─────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS protocol_flags (
      id         SERIAL PRIMARY KEY,
      tenant_id  INT         NOT NULL REFERENCES tenants(id),
      thread_id  VARCHAR(64) NOT NULL,
      account_id INT         REFERENCES accounts(id) ON DELETE SET NULL,
      type       VARCHAR(20) NOT NULL DEFAULT 'complaint'
                   CHECK (type IN ('complaint','suggestion','compliment')),
      note       TEXT,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_protocol_flags_tenant ON protocol_flags(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_protocol_flags_thread ON protocol_flags(thread_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_protocol_flags_type   ON protocol_flags(type)`)
  console.log('✅ Fase 4 — protocol_ratings, protocol_flags criadas/verificadas')

  // ── Worker — tabela de falhas definitivas de envio ────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS notification_errors (
      id            SERIAL PRIMARY KEY,
      job_id        VARCHAR(64),
      log_id        INT,
      phone         VARCHAR(20),
      type          VARCHAR(64),
      error_message TEXT,
      payload       JSONB,
      tenant_id     INT,
      created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_notif_errors_tenant  ON notification_errors(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_notif_errors_created ON notification_errors(created_at DESC)`)
  console.log('✅ Worker — tabela notification_errors verificada')

  // ── Fase 12 — Equipe Virtual ─────────────────────────────────────────────
  // accounts: colaboradores internos com cargo e número pessoal
  await execute(`
    CREATE TABLE IF NOT EXISTS accounts (
      id              SERIAL PRIMARY KEY,
      tenant_id       INT          NOT NULL REFERENCES tenants(id),
      name            VARCHAR(255) NOT NULL,
      email           VARCHAR(255),
      password_hash   VARCHAR(255),
      role            VARCHAR(20)  NOT NULL DEFAULT 'agent'
                        CHECK (role IN ('owner','manager','supervisor','secretary','agent','viewer')),
      phone           VARCHAR(30),
      phone_connected BOOLEAN      NOT NULL DEFAULT FALSE,
      availability    VARCHAR(10)  NOT NULL DEFAULT 'offline'
                        CHECK (availability IN ('online','busy','offline')),
      avatar_url      TEXT,
      active          BOOLEAN      NOT NULL DEFAULT TRUE,
      created_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_accounts_email  ON accounts(tenant_id, email) WHERE email IS NOT NULL`)
  await execute(`CREATE INDEX        IF NOT EXISTS idx_accounts_tenant ON accounts(tenant_id)`)
  await execute(`CREATE INDEX        IF NOT EXISTS idx_accounts_role   ON accounts(tenant_id, role)`)

  // sectors: setores operacionais da empresa
  await execute(`
    CREATE TABLE IF NOT EXISTS sectors (
      id          SERIAL PRIMARY KEY,
      tenant_id   INT          NOT NULL REFERENCES tenants(id),
      name        VARCHAR(255) NOT NULL,
      description TEXT,
      icon        VARCHAR(80)  NOT NULL DEFAULT 'Briefcase',
      color       VARCHAR(20)  NOT NULL DEFAULT '#6366f1',
      sla_minutes INT          NOT NULL DEFAULT 60,
      sort_order  INT          NOT NULL DEFAULT 0,
      active      BOOLEAN      NOT NULL DEFAULT TRUE,
      created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_sectors_tenant ON sectors(tenant_id, active)`)

  // team_members: relacionamento conta ↔ setor
  await execute(`
    CREATE TABLE IF NOT EXISTS team_members (
      id                SERIAL PRIMARY KEY,
      account_id        INT          NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
      sector_id         INT          NOT NULL REFERENCES sectors(id)  ON DELETE CASCADE,
      function          VARCHAR(255),
      is_primary        BOOLEAN      NOT NULL DEFAULT FALSE,
      notify_escalation BOOLEAN      NOT NULL DEFAULT TRUE,
      notify_human_api  BOOLEAN      NOT NULL DEFAULT TRUE,
      on_duty           BOOLEAN      NOT NULL DEFAULT FALSE,
      created_at        TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      UNIQUE (account_id, sector_id)
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_team_members_account ON team_members(account_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_team_members_sector  ON team_members(sector_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_team_members_duty    ON team_members(sector_id, on_duty)`)

  // sector_brain_nodes: cérebro de conhecimento por setor
  await execute(`
    CREATE TABLE IF NOT EXISTS sector_brain_nodes (
      id         SERIAL PRIMARY KEY,
      sector_id  INT         NOT NULL REFERENCES sectors(id) ON DELETE CASCADE,
      type       VARCHAR(20) NOT NULL DEFAULT 'knowledge'
                   CHECK (type IN ('knowledge','rules','escalation','persona')),
      content    TEXT        NOT NULL,
      sort_order INT         NOT NULL DEFAULT 0,
      active     BOOLEAN     NOT NULL DEFAULT TRUE,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_sector_brain_sector ON sector_brain_nodes(sector_id, active)`)

  // internal_messages: inbox interna (equipe ↔ equipe, Human API, escalações)
  await execute(`
    CREATE TABLE IF NOT EXISTS internal_messages (
      id           SERIAL PRIMARY KEY,
      tenant_id    INT         NOT NULL REFERENCES tenants(id),
      thread_id    VARCHAR(64) NOT NULL,
      from_account INT         REFERENCES accounts(id) ON DELETE SET NULL,
      to_account   INT         REFERENCES accounts(id) ON DELETE SET NULL,
      sector_id    INT         REFERENCES sectors(id)  ON DELETE SET NULL,
      type         VARCHAR(20) NOT NULL DEFAULT 'collaboration'
                     CHECK (type IN ('human_api','escalation','collaboration','system','help_request')),
      content      TEXT        NOT NULL,
      ref_id       VARCHAR(64),
      read_at      TIMESTAMPTZ,
      created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_internal_msgs_tenant ON internal_messages(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_internal_msgs_thread ON internal_messages(thread_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_internal_msgs_to     ON internal_messages(to_account, read_at)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_internal_msgs_sector ON internal_messages(sector_id)`)

  // human_api_requests: consultas da IA para especialistas humanos
  await execute(`
    CREATE TABLE IF NOT EXISTS human_api_requests (
      id              SERIAL PRIMARY KEY,
      tenant_id       INT         NOT NULL REFERENCES tenants(id),
      conversation_id VARCHAR(64),
      sector_id       INT         REFERENCES sectors(id)  ON DELETE SET NULL,
      account_id      INT         REFERENCES accounts(id) ON DELETE SET NULL,
      question        TEXT        NOT NULL,
      answer          TEXT,
      status          VARCHAR(20) NOT NULL DEFAULT 'pending'
                        CHECK (status IN ('pending','answered','timeout','ignored')),
      delivery_mode   VARCHAR(20) NOT NULL DEFAULT 'inbox_interna'
                        CHECK (delivery_mode IN ('whatsapp','inbox_interna')),
      asked_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      answered_at     TIMESTAMPTZ,
      timeout_at      TIMESTAMPTZ
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_human_api_tenant  ON human_api_requests(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_human_api_status  ON human_api_requests(status)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_human_api_account ON human_api_requests(account_id)`)

  // knowledge_learning: respostas humanas que podem virar base de conhecimento
  await execute(`
    CREATE TABLE IF NOT EXISTS knowledge_learning (
      id           SERIAL PRIMARY KEY,
      tenant_id    INT         NOT NULL REFERENCES tenants(id),
      sector_id    INT         REFERENCES sectors(id)  ON DELETE SET NULL,
      account_id   INT         REFERENCES accounts(id) ON DELETE SET NULL,
      question     TEXT        NOT NULL,
      answer       TEXT        NOT NULL,
      promoted     BOOLEAN     NOT NULL DEFAULT FALSE,
      promoted_at  TIMESTAMPTZ,
      use_count    INT         NOT NULL DEFAULT 0,
      created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_knowledge_tenant   ON knowledge_learning(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_knowledge_sector   ON knowledge_learning(sector_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_knowledge_promoted ON knowledge_learning(promoted)`)

  // Adiciona chat_id em internal_messages (necessário para encerrar protocolo sem prompt)
  await execute(`ALTER TABLE internal_messages ADD COLUMN IF NOT EXISTS chat_id VARCHAR(128)`)

  // ── Direct Messages (DMs entre colaboradores) ──────────────────────────────────
  // Fase 13: Comunicação interna entre colaboradores (não vinculada a escalação/protocol)
  await execute(`
    CREATE TABLE IF NOT EXISTS direct_messages (
      id            SERIAL PRIMARY KEY,
      tenant_id     INT          NOT NULL REFERENCES tenants(id),
      from_account  INT          NOT NULL REFERENCES accounts(id) ON DELETE SET NULL,
      to_account    INT          NOT NULL REFERENCES accounts(id) ON DELETE SET NULL,
      content       TEXT         NOT NULL,
      read_at       TIMESTAMPTZ,
      created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_dm_tenant      ON direct_messages(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_dm_from_to     ON direct_messages(from_account, to_account)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_dm_read_status ON direct_messages(to_account, read_at)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_dm_created     ON direct_messages(created_at DESC)`)

  console.log('✅ Fase 12 — Equipe Virtual: accounts, sectors, team_members, sector_brain_nodes, internal_messages, human_api_requests, knowledge_learning')
  console.log('✅ Fase 13 — Direct Messages: DMs entre colaboradores')

  // ── Group Chats por Setor ─────────────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS group_chats (
      id         SERIAL PRIMARY KEY,
      tenant_id  INT          NOT NULL REFERENCES tenants(id),
      sector_id  INT          NOT NULL REFERENCES sectors(id) ON DELETE CASCADE,
      name       VARCHAR(255) NOT NULL,
      created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      UNIQUE (tenant_id, sector_id)
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_group_chats_tenant  ON group_chats(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_group_chats_sector  ON group_chats(sector_id)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS group_messages (
      id            SERIAL PRIMARY KEY,
      tenant_id     INT  NOT NULL REFERENCES tenants(id),
      group_chat_id INT  NOT NULL REFERENCES group_chats(id) ON DELETE CASCADE,
      from_account  INT  REFERENCES accounts(id) ON DELETE SET NULL,
      content       TEXT NOT NULL,
      created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_gm_group    ON group_messages(group_chat_id, created_at DESC)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_gm_tenant   ON group_messages(tenant_id)`)

  // Seed: cria group_chat para cada setor que ainda não tem
  await execute(`
    INSERT INTO group_chats (tenant_id, sector_id, name)
    SELECT s.tenant_id, s.id, s.name
    FROM sectors s
    WHERE s.active = TRUE
      AND NOT EXISTS (
        SELECT 1 FROM group_chats g WHERE g.sector_id = s.id
      )
  `)
  console.log('✅ Fase 14 — Group Chats: group_chats, group_messages (seed por setor)')

  // ── Broadcasts ────────────────────────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS broadcasts (
      id           SERIAL PRIMARY KEY,
      tenant_id    INT  NOT NULL REFERENCES tenants(id),
      from_account INT  REFERENCES accounts(id) ON DELETE SET NULL,
      content      TEXT NOT NULL,
      created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_broadcasts_tenant ON broadcasts(tenant_id, created_at DESC)`)
  console.log('✅ Fase 15 — Broadcasts: tabela broadcasts')

  // ── Leitura: grupos e broadcasts ──────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS group_last_read (
      account_id    INT         NOT NULL REFERENCES accounts(id)    ON DELETE CASCADE,
      group_chat_id INT         NOT NULL REFERENCES group_chats(id) ON DELETE CASCADE,
      last_read_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      PRIMARY KEY (account_id, group_chat_id)
    )
  `)
  await execute(`
    CREATE TABLE IF NOT EXISTS broadcast_last_seen (
      account_id   INT         NOT NULL REFERENCES accounts(id) ON DELETE CASCADE,
      tenant_id    INT         NOT NULL REFERENCES tenants(id)  ON DELETE CASCADE,
      last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      PRIMARY KEY (account_id, tenant_id)
    )
  `)
  console.log('✅ Fase 16 — Leitura: group_last_read, broadcast_last_seen')

  // ── Descontos por quantidade em sorteios ─────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS raffle_discounts (
      id           SERIAL PRIMARY KEY,
      raffle_id    INT     NOT NULL REFERENCES raffles(id) ON DELETE CASCADE,
      min_qty      INT     NOT NULL CHECK (min_qty >= 2),
      discount_pct NUMERIC(5,2) NOT NULL CHECK (discount_pct > 0 AND discount_pct <= 100),
      active       BOOLEAN NOT NULL DEFAULT TRUE,
      created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      UNIQUE (raffle_id, min_qty)
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_raffle_discounts_raffle ON raffle_discounts(raffle_id) WHERE active = TRUE`)
  console.log('✅ raffle_discounts — descontos por quantidade verificados')

  // ── Promoções Relâmpago ───────────────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS raffle_flash_promos (
      id           SERIAL PRIMARY KEY,
      raffle_id    INT          NOT NULL REFERENCES raffles(id) ON DELETE CASCADE,
      discount_pct NUMERIC(5,2) NOT NULL CHECK (discount_pct > 0 AND discount_pct <= 100),
      label        VARCHAR(255) NOT NULL DEFAULT 'Promoção Relâmpago',
      starts_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      ends_at      TIMESTAMPTZ  NOT NULL,
      created_at   TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_flash_promos_raffle ON raffle_flash_promos(raffle_id, ends_at)`)
  console.log('✅ raffle_flash_promos — promoções relâmpago verificadas')

  // ── Módulo Cotação Online ──────────────────────────────────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS clientes (
      id            SERIAL PRIMARY KEY,
      tenant_id     INT          NOT NULL DEFAULT 1,
      tipo          VARCHAR(2)   NOT NULL CHECK (tipo IN ('PF','PJ')),
      nome          VARCHAR(255) NOT NULL,
      cpf_cnpj      VARCHAR(20)  NOT NULL,
      email         VARCHAR(255),
      status        VARCHAR(10)  NOT NULL DEFAULT 'ativo' CHECK (status IN ('ativo','inativo')),
      user_id       INT          REFERENCES users(id) ON DELETE SET NULL,
      created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      updated_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_clientes_tenant ON clientes(tenant_id)`)
  await execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_clientes_cpf_tenant ON clientes(cpf_cnpj, tenant_id)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS cliente_enderecos (
      id            SERIAL PRIMARY KEY,
      cliente_id    INT          NOT NULL REFERENCES clientes(id) ON DELETE CASCADE,
      tipo          VARCHAR(20)  NOT NULL DEFAULT 'entrega' CHECK (tipo IN ('entrega','cobranca','retirada','matriz','filial')),
      cep           VARCHAR(10),
      rua           VARCHAR(255),
      numero        VARCHAR(20),
      complemento   VARCHAR(100),
      bairro        VARCHAR(100),
      cidade        VARCHAR(100),
      estado        VARCHAR(2),
      referencia    VARCHAR(255),
      principal     BOOLEAN      NOT NULL DEFAULT FALSE,
      created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_enderecos_cliente ON cliente_enderecos(cliente_id)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS cliente_telefones (
      id              SERIAL PRIMARY KEY,
      cliente_id      INT          NOT NULL REFERENCES clientes(id) ON DELETE CASCADE,
      tipo            VARCHAR(20)  NOT NULL DEFAULT 'celular' CHECK (tipo IN ('comercial','celular','whatsapp','financeiro','compras')),
      numero          VARCHAR(20)  NOT NULL,
      ramal           VARCHAR(10),
      aceita_whatsapp BOOLEAN      NOT NULL DEFAULT FALSE,
      principal       BOOLEAN      NOT NULL DEFAULT FALSE,
      created_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_telefones_cliente ON cliente_telefones(cliente_id)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS cliente_responsaveis (
      id            SERIAL PRIMARY KEY,
      cliente_id    INT          NOT NULL REFERENCES clientes(id) ON DELETE CASCADE,
      nome          VARCHAR(255) NOT NULL,
      cargo         VARCHAR(100),
      setor         VARCHAR(100),
      telefone_id   INT          REFERENCES cliente_telefones(id) ON DELETE SET NULL,
      email         VARCHAR(255),
      permissao     VARCHAR(100),
      created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_responsaveis_cliente ON cliente_responsaveis(cliente_id)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS produtos (
      id            SERIAL PRIMARY KEY,
      tenant_id     INT             NOT NULL DEFAULT 1,
      sku           VARCHAR(100),
      nome          VARCHAR(255)    NOT NULL,
      descricao     TEXT,
      unidade       VARCHAR(20)     DEFAULT 'un',
      preco              NUMERIC(10,2)   NOT NULL DEFAULT 0,
      preco_promocional  NUMERIC(10,2)   DEFAULT NULL,
      estoque            NUMERIC(10,3)   NOT NULL DEFAULT 0,
      categoria          VARCHAR(100),
      imagem             TEXT,
      ativo              BOOLEAN         NOT NULL DEFAULT TRUE,
      created_at         TIMESTAMPTZ     NOT NULL DEFAULT NOW(),
      updated_at         TIMESTAMPTZ     NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_produtos_tenant ON produtos(tenant_id)`)
  await execute(`CREATE UNIQUE INDEX IF NOT EXISTS idx_produtos_sku_tenant ON produtos(sku, tenant_id) WHERE sku IS NOT NULL`)

  await execute(`
    CREATE TABLE IF NOT EXISTS cotacoes (
      id            SERIAL PRIMARY KEY,
      tenant_id     INT          NOT NULL DEFAULT 1,
      cliente_id    INT          REFERENCES clientes(id) ON DELETE SET NULL,
      user_id       INT          REFERENCES users(id) ON DELETE SET NULL,
      status        VARCHAR(20)  NOT NULL DEFAULT 'rascunho' CHECK (status IN ('rascunho','salva','finalizada','cancelada')),
      forma_pagto   VARCHAR(20)  CHECK (forma_pagto IN ('pix','cartao','faturado')),
      total         NUMERIC(10,2) NOT NULL DEFAULT 0,
      desconto      NUMERIC(10,2) NOT NULL DEFAULT 0,
      observacao    TEXT,
      created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      updated_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_cotacoes_tenant ON cotacoes(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_cotacoes_cliente ON cotacoes(cliente_id)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS cotacao_itens (
      id              SERIAL PRIMARY KEY,
      cotacao_id      INT             NOT NULL REFERENCES cotacoes(id) ON DELETE CASCADE,
      produto_id      INT             REFERENCES produtos(id) ON DELETE SET NULL,
      nome_produto    VARCHAR(255)    NOT NULL,
      sku             VARCHAR(100),
      quantidade      NUMERIC(10,3)   NOT NULL DEFAULT 1,
      preco_unitario  NUMERIC(10,2)   NOT NULL,
      preco_promocional NUMERIC(10,2),
      desconto_pct    NUMERIC(5,2)    DEFAULT 0,
      subtotal        NUMERIC(10,2)   NOT NULL,
      created_at      TIMESTAMPTZ     NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_cotacao_itens_cotacao ON cotacao_itens(cotacao_id)`)

  await execute(`
    CREATE TABLE IF NOT EXISTS pedidos (
      id            SERIAL PRIMARY KEY,
      tenant_id     INT          NOT NULL DEFAULT 1,
      cotacao_id    INT          REFERENCES cotacoes(id) ON DELETE SET NULL,
      cliente_id    INT          REFERENCES clientes(id) ON DELETE SET NULL,
      user_id       INT          REFERENCES users(id) ON DELETE SET NULL,
      endereco_id   INT          REFERENCES cliente_enderecos(id) ON DELETE SET NULL,
      status        VARCHAR(20)  NOT NULL DEFAULT 'aguardando' CHECK (status IN ('aguardando','separacao','embalagem','auditoria','fiscal','expedicao','entregue','cancelado')),
      forma_pagto   VARCHAR(20)  CHECK (forma_pagto IN ('pix','cartao','faturado')),
      tipo_entrega  VARCHAR(20)  NOT NULL DEFAULT 'retirada' CHECK (tipo_entrega IN ('retirada','entrega')),
      total         NUMERIC(10,2) NOT NULL DEFAULT 0,
      desconto      NUMERIC(10,2) NOT NULL DEFAULT 0,
      observacao    TEXT,
      equipe_id     INT,
      responsavel_entrega TEXT,
      entregue_em   TIMESTAMPTZ,
      created_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      updated_at    TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_tenant ON pedidos(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_status ON pedidos(tenant_id, status)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_cliente ON pedidos(cliente_id)`)

  // Histórico de status — registra cada transição com timestamp
  await execute(`
    CREATE TABLE IF NOT EXISTS pedido_status_log (
      id         SERIAL PRIMARY KEY,
      pedido_id  INT          NOT NULL REFERENCES pedidos(id) ON DELETE CASCADE,
      status     VARCHAR(20)  NOT NULL,
      account_id INT,
      created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedido_status_log ON pedido_status_log(pedido_id, created_at)`)
  // Seed retroativo: garante pelo menos a entrada inicial para pedidos existentes
  await execute(`
    INSERT INTO pedido_status_log (pedido_id, status, created_at)
    SELECT id, 'aguardando', created_at FROM pedidos
    WHERE NOT EXISTS (
      SELECT 1 FROM pedido_status_log l WHERE l.pedido_id = pedidos.id
    )
  `)

  await execute(`
    CREATE TABLE IF NOT EXISTS pedido_itens (
      id              SERIAL PRIMARY KEY,
      pedido_id       INT             NOT NULL REFERENCES pedidos(id) ON DELETE CASCADE,
      produto_id      INT             REFERENCES produtos(id) ON DELETE SET NULL,
      nome_produto    VARCHAR(255)    NOT NULL,
      sku             VARCHAR(100),
      quantidade      NUMERIC(10,3)   NOT NULL DEFAULT 1,
      preco_unitario    NUMERIC(10,2)   NOT NULL,
      preco_promocional NUMERIC(10,2)   DEFAULT NULL,
      desconto_pct      NUMERIC(5,2)    DEFAULT 0,
      subtotal          NUMERIC(10,2)   NOT NULL,
      separado          BOOLEAN         NOT NULL DEFAULT FALSE,
      created_at        TIMESTAMPTZ     NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedido_itens_pedido ON pedido_itens(pedido_id)`)

  // promotions: garantir tenant_id e ativo BOOLEAN (produto_id removido — promoções são marketing independente)
  await execute(`ALTER TABLE promotions ADD COLUMN IF NOT EXISTS tenant_id INT`)
  await execute(`ALTER TABLE promotions ALTER COLUMN ativo DROP DEFAULT`)
  await execute(`ALTER TABLE promotions ALTER COLUMN ativo TYPE BOOLEAN USING (CASE WHEN ativo::text IN ('1','true') THEN TRUE ELSE FALSE END)`)
  await execute(`ALTER TABLE promotions ALTER COLUMN ativo SET DEFAULT TRUE`)
  // novos campos de produto e pedido_itens
  await execute(`ALTER TABLE produtos ADD COLUMN IF NOT EXISTS preco_promocional NUMERIC(10,2) DEFAULT NULL`)
  await execute(`ALTER TABLE pedido_itens ADD COLUMN IF NOT EXISTS preco_promocional NUMERIC(10,2) DEFAULT NULL`)

  // EMB-02 — registro de embalador e timestamp
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS embalador TEXT`)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS embalado_em TIMESTAMPTZ`)

  // WPP-10 — número de protocolo por pedido (PED-YYYYMMDD-ID)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS protocolo VARCHAR(30)`)

  // PROMO-10 — promoções relâmpago para cotações (reutiliza padrão raffle_flash_promos)
  await execute(`
    CREATE TABLE IF NOT EXISTS cotacao_flash_promos (
      id             SERIAL PRIMARY KEY,
      tenant_id      INT          NOT NULL DEFAULT 1,
      produto_id     INT          REFERENCES produtos(id) ON DELETE SET NULL,
      discount_pct   NUMERIC(5,2) NOT NULL,
      label          VARCHAR(120) NOT NULL DEFAULT 'Promoção Relâmpago',
      starts_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW(),
      ends_at        TIMESTAMPTZ  NOT NULL,
      ativo          BOOLEAN      NOT NULL DEFAULT TRUE,
      created_at     TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_cfp_tenant ON cotacao_flash_promos(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_cfp_ativo  ON cotacao_flash_promos(tenant_id, ativo) WHERE ativo = TRUE`)

  // WPP-09 — log de mensagens de reativação enviadas
  await execute(`
    CREATE TABLE IF NOT EXISTS wpp_reativacao_log (
      id         SERIAL PRIMARY KEY,
      tenant_id  INT         NOT NULL DEFAULT 1,
      cliente_id INT         REFERENCES clientes(id) ON DELETE SET NULL,
      chat_id    TEXT        NOT NULL,
      mensagem   TEXT,
      enviada_em TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_wpp_reat_tenant   ON wpp_reativacao_log(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_wpp_reat_cliente  ON wpp_reativacao_log(cliente_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_wpp_reat_chat     ON wpp_reativacao_log(chat_id)`)

  // INB-01/02/03 — Inbox interno por setor vinculado ao pedido
  await execute(`
    CREATE TABLE IF NOT EXISTS mensagens_internas (
      id          SERIAL PRIMARY KEY,
      tenant_id   INT          NOT NULL DEFAULT 1,
      pedido_id   INT          REFERENCES pedidos(id) ON DELETE CASCADE,
      setor       VARCHAR(30)  NOT NULL DEFAULT 'geral'
                               CHECK (setor IN ('geral','atendimento','cotacao','separacao','embalagem','auditoria','fiscal','expedicao','financeiro','suporte')),
      remetente   VARCHAR(120) NOT NULL,
      mensagem    TEXT         NOT NULL,
      lida        BOOLEAN      NOT NULL DEFAULT FALSE,
      created_at  TIMESTAMPTZ  NOT NULL DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_msg_int_tenant  ON mensagens_internas(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_msg_int_pedido  ON mensagens_internas(pedido_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_msg_int_setor   ON mensagens_internas(tenant_id, setor)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_msg_int_nao_lida ON mensagens_internas(tenant_id, lida) WHERE lida = FALSE`)
  // Migração: coluna chat_id para vincular alertas do Monitor IA ao chat WhatsApp
  await execute(`ALTER TABLE mensagens_internas ADD COLUMN IF NOT EXISTS chat_id VARCHAR(120)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_msg_int_chat_id ON mensagens_internas(chat_id) WHERE chat_id IS NOT NULL`)
  // Observação por item do carrinho (variedades, tamanhos, etc.)
  await execute(`ALTER TABLE cotacao_itens  ADD COLUMN IF NOT EXISTS observacao VARCHAR(500)`)
  await execute(`ALTER TABLE pedido_itens   ADD COLUMN IF NOT EXISTS observacao VARCHAR(500)`)
  // chat_id em human_api_requests — permite Monitor IA suprimir re-alertas
  await execute(`ALTER TABLE human_api_requests ADD COLUMN IF NOT EXISTS chat_id VARCHAR(120)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_har_chat_id ON human_api_requests(chat_id) WHERE chat_id IS NOT NULL`)
  // Alertas de item pelo separador (falta, marca diferente, substituição + foto)
  await execute(`ALTER TABLE pedido_itens ADD COLUMN IF NOT EXISTS alerta_tipo     VARCHAR(30)`)
  await execute(`ALTER TABLE pedido_itens ADD COLUMN IF NOT EXISTS alerta_obs      VARCHAR(500)`)
  await execute(`ALTER TABLE pedido_itens ADD COLUMN IF NOT EXISTS alerta_foto     VARCHAR(500)`)
  await execute(`ALTER TABLE pedido_itens ADD COLUMN IF NOT EXISTS alerta_confirmado BOOLEAN DEFAULT FALSE`)
  await execute(`ALTER TABLE pedido_itens ADD COLUMN IF NOT EXISTS alerta_em       TIMESTAMPTZ`)

  // ── FUT-02: Pedidos Recorrentes (recompra automática PJ) ─────────────────────
  await execute(`
    CREATE TABLE IF NOT EXISTS pedidos_recorrentes (
      id           SERIAL PRIMARY KEY,
      tenant_id    INT          NOT NULL DEFAULT 1,
      user_id      INT          REFERENCES users(id) ON DELETE CASCADE,
      cliente_id   INT          REFERENCES clientes(id) ON DELETE SET NULL,
      nome         VARCHAR(200) NOT NULL DEFAULT 'Pedido Recorrente',
      itens        JSONB        NOT NULL DEFAULT '[]',
      frequencia   VARCHAR(20)  NOT NULL DEFAULT 'mensal',
      proximo_em   DATE         NOT NULL,
      ativo        BOOLEAN      NOT NULL DEFAULT TRUE,
      pausado      BOOLEAN      NOT NULL DEFAULT FALSE,
      created_at   TIMESTAMPTZ  DEFAULT NOW(),
      updated_at   TIMESTAMPTZ  DEFAULT NOW()
    )
  `)
  await execute(`CREATE INDEX IF NOT EXISTS idx_rec_tenant  ON pedidos_recorrentes(tenant_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_rec_user    ON pedidos_recorrentes(user_id)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_rec_prox    ON pedidos_recorrentes(proximo_em) WHERE ativo = TRUE AND pausado = FALSE`)

  console.log('✅ Módulo Cotação Online — tabelas verificadas')

  // ── Colaboradores Bridge — vínculo WA-Inbox + FK de embalador ────────────
  await execute(`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS nw_team_id   TEXT`)
  await execute(`ALTER TABLE accounts ADD COLUMN IF NOT EXISTS nw_sector_id TEXT`)
  await execute(`ALTER TABLE pedidos  ADD COLUMN IF NOT EXISTS embalador_id BIGINT REFERENCES accounts(id) ON DELETE SET NULL`)
  await execute(`ALTER TABLE pedidos  ADD COLUMN IF NOT EXISTS expedidor_id BIGINT REFERENCES accounts(id) ON DELETE SET NULL`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_embalador ON pedidos(embalador_id) WHERE embalador_id IS NOT NULL`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_expedidor ON pedidos(expedidor_id) WHERE expedidor_id IS NOT NULL`)
  // Migração best-effort: texto livre → FK para registros já existentes
  await execute(`
    UPDATE pedidos p SET embalador_id = a.id
    FROM accounts a
    WHERE a.tenant_id = p.tenant_id
      AND LOWER(TRIM(a.name)) = LOWER(TRIM(p.embalador))
      AND p.embalador IS NOT NULL
      AND p.embalador_id IS NULL
  `)
  console.log('✅ Colaboradores Bridge — nw_team_id, embalador_id, expedidor_id verificados')

  // ── Cotação Funções Operacionais — separador/auditor/fiscal ──────────────
  // Cada etapa do fluxo (separação, embalagem, auditoria, fiscal, expedição) é
  // atendida pelos colaboradores cujo setor (sectors.name via team_members)
  // bate com o nome da função. Sem tabela de mapeamento — o setor já é a fonte
  // da verdade, gerenciado em /admin-v2/equipe.
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS separador_id BIGINT REFERENCES accounts(id) ON DELETE SET NULL`)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS auditor_id   BIGINT REFERENCES accounts(id) ON DELETE SET NULL`)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS fiscal_id    BIGINT REFERENCES accounts(id) ON DELETE SET NULL`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_separador ON pedidos(separador_id) WHERE separador_id IS NOT NULL`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_auditor   ON pedidos(auditor_id)   WHERE auditor_id   IS NOT NULL`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_pedidos_fiscal    ON pedidos(fiscal_id)    WHERE fiscal_id    IS NOT NULL`)
  console.log('✅ Cotação Funções — separador_id, auditor_id, fiscal_id verificados')

  // ── Cupom fiscal + saída do entregador ────────────────────────────────────
  // Sem integração SEFAZ: registro manual do número/chave de acesso do cupom
  // emitido externamente (PDV/ECF). Permite emitir em qualquer fase pós-pagto;
  // a coluna emitido_por mantém quem clicou no botão para auditoria.
  // expedidor_saida_em é setado automaticamente quando o pedido entra em
  // 'expedicao' — é o "horário de saída do entregador".
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS cupom_numero       VARCHAR(60)`)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS cupom_chave        VARCHAR(64)`)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS cupom_emitido_em   TIMESTAMPTZ`)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS cupom_emitido_por  BIGINT REFERENCES accounts(id) ON DELETE SET NULL`)
  await execute(`ALTER TABLE pedidos ADD COLUMN IF NOT EXISTS expedidor_saida_em TIMESTAMPTZ`)
  console.log('✅ Cotação Fiscal — cupom_numero, cupom_chave, cupom_emitido_em, cupom_emitido_por, expedidor_saida_em verificados')

  // ── Captive Portal Integration ─────────────────────────────────────────────
  // Armazena o session_id gerado pelo sistema-local para rastrear qual usuário
  // confirmou a landing page e liberou a internet.
  await execute(`ALTER TABLE users ADD COLUMN IF NOT EXISTS portal_session_id VARCHAR(64)`)
  await execute(`CREATE INDEX IF NOT EXISTS idx_users_portal_session ON users(portal_session_id) WHERE portal_session_id IS NOT NULL`)
  console.log('✅ Captive Portal — coluna portal_session_id verificada')
}

// saveDatabase é no-op no PostgreSQL (era necessário apenas no sql.js)
function saveDatabase() {}

module.exports = {
  initialize,
  saveDatabase,
  // Para compatibilidade com plugins que ainda usam a API síncrona do sql.js:
  runQuery: (...args) => { throw new Error('Use execute() do postgres.js diretamente') },
  getOne:   (...args) => { throw new Error('Use queryOne() do postgres.js diretamente') },
  getAll:   (...args) => { throw new Error('Use query() do postgres.js diretamente')   },
}
