'use strict'

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

class Cotacao {
  static findById(id) {
    return queryOne(`
      SELECT c.*,
             COALESCE(cl.nome, u.nome) AS cliente_nome,
             COALESCE(cl.tipo, 'PF')   AS cliente_tipo
      FROM cotacoes c
      LEFT JOIN clientes cl ON cl.id  = c.cliente_id
      LEFT JOIN users    u  ON u.id   = c.user_id
      WHERE c.id = $1
    `, [id])
  }

  static listByCliente(clienteId, tenantId) {
    return query(
      `SELECT * FROM cotacoes WHERE cliente_id = $1 AND tenant_id = $2 ORDER BY created_at DESC`,
      [clienteId, tenantId]
    )
  }

  static listByUser(userId, tenantId) {
    return query(
      `SELECT DISTINCT ON (c.id) c.*,
              p.id           AS pedido_id,
              p.protocolo    AS pedido_protocolo,
              p.status       AS pedido_status,
              p.forma_pagto  AS pedido_forma_pagto,
              p.tipo_entrega AS pedido_tipo_entrega,
              p.financeiro_status AS pedido_financeiro_status,
              (
                SELECT json_agg(json_build_object(
                  'status', sl.status,
                  'created_at', sl.created_at
                ) ORDER BY sl.created_at ASC)
                FROM pedido_status_log sl
                WHERE sl.pedido_id = p.id
              ) AS pedido_status_log,
              (
                SELECT json_agg(json_build_object(
                  'id',               pi.id,
                  'nome_produto',     pi.nome_produto,
                  'sku',              pi.sku,
                  'quantidade',       pi.quantidade,
                  'subtotal',         pi.subtotal,
                  'observacao',       pi.observacao,
                  'alerta_tipo',      pi.alerta_tipo,
                  'alerta_obs',       pi.alerta_obs,
                  'alerta_foto',      pi.alerta_foto,
                  'alerta_confirmado',pi.alerta_confirmado,
                  'alerta_em',        pi.alerta_em
                ) ORDER BY pi.id ASC)
                FROM pedido_itens pi
                WHERE pi.pedido_id = p.id
              ) AS itens
       FROM cotacoes c
       LEFT JOIN pedidos p ON p.cotacao_id = c.id AND p.tenant_id = c.tenant_id
       WHERE c.user_id = $1 AND c.tenant_id = $2
       ORDER BY c.id DESC, p.id DESC
       LIMIT 50`,
      [userId, tenantId]
    )
  }

  static listAdmin(tenantId, { status, limit = 50, offset = 0 } = {}) {
    const params = [tenantId]
    let where = 'WHERE c.tenant_id = $1'
    if (status) { params.push(status); where += ` AND c.status = $${params.length}` }
    params.push(Math.min(Number(limit) || 50, 200))
    params.push(Math.max(Number(offset) || 0, 0))
    return query(
      `SELECT c.*,
              COALESCE(cl.nome, u.nome) AS cliente_nome,
              COALESCE(cl.tipo, 'PF')   AS cliente_tipo
       FROM cotacoes c
       LEFT JOIN clientes cl ON cl.id = c.cliente_id
       LEFT JOIN users    u  ON u.id  = c.user_id
       ${where} ORDER BY c.created_at DESC
       LIMIT $${params.length - 1} OFFSET $${params.length}`,
      params
    )
  }

  static create({ tenant_id, cliente_id, user_id, status = 'rascunho', forma_pagto, total, desconto, observacao }) {
    return execute(
      `INSERT INTO cotacoes (tenant_id,cliente_id,user_id,status,forma_pagto,total,desconto,observacao)
       VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING *`,
      [tenant_id, cliente_id || null, user_id || null, status,
       forma_pagto || null, total || 0, desconto || 0, observacao || null]
    )
  }

  static update(id, { status, forma_pagto, total, desconto, observacao }) {
    return execute(
      `UPDATE cotacoes SET status=$1,forma_pagto=$2,total=$3,desconto=$4,observacao=$5,updated_at=NOW()
       WHERE id=$6`,
      [status, forma_pagto || null, total, desconto || 0, observacao || null, id]
    )
  }

  // ── Itens ─────────────────────────────────────────────────

  static listItens(cotacaoId) {
    return query(
      `SELECT ci.*, p.imagem AS produto_imagem
       FROM cotacao_itens ci
       LEFT JOIN produtos p ON p.id = ci.produto_id
       WHERE ci.cotacao_id = $1 ORDER BY ci.id ASC`,
      [cotacaoId]
    )
  }

  static addItem({ cotacao_id, produto_id, nome_produto, sku, quantidade, preco_unitario, preco_promocional, desconto_pct, observacao }) {
    const precoFinal = preco_promocional || preco_unitario
    const subtotal   = precoFinal * quantidade * (1 - (desconto_pct || 0) / 100)
    return execute(
      `INSERT INTO cotacao_itens
         (cotacao_id,produto_id,nome_produto,sku,quantidade,preco_unitario,preco_promocional,desconto_pct,subtotal,observacao)
       VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) RETURNING *`,
      [cotacao_id, produto_id || null, nome_produto, sku || null,
       quantidade, preco_unitario, preco_promocional || null, desconto_pct || 0, subtotal, observacao || null]
    )
  }

  static updateItemObs(itemId, observacao) {
    return execute(
      `UPDATE cotacao_itens SET observacao=$1 WHERE id=$2`,
      [observacao || null, itemId]
    )
  }

  static removeItem(itemId) {
    return execute('DELETE FROM cotacao_itens WHERE id = $1', [itemId])
  }

  static clearItens(cotacaoId) {
    return execute('DELETE FROM cotacao_itens WHERE cotacao_id = $1', [cotacaoId])
  }

  static async recalcTotal(cotacaoId) {
    await execute(
      `UPDATE cotacoes SET total = (
         SELECT COALESCE(SUM(subtotal),0) FROM cotacao_itens WHERE cotacao_id = $1
       ), updated_at = NOW() WHERE id = $1`,
      [cotacaoId]
    )
  }

  // ── Converter cotação em pedido ───────────────────────────

  static async toOrder(cotacaoId, { endereco_id, tipo_entrega, observacao } = {}) {
    const cotacao = await Cotacao.findById(cotacaoId)
    if (!cotacao) throw new Error('Cotação não encontrada')
    const itens = await Cotacao.listItens(cotacaoId)

    // Strategy 2 — se veio do portal (user_id preenchido mas cliente_id nulo),
    // garante um registro em clientes para manter rastreabilidade no admin
    let clienteId = cotacao.cliente_id
    if (!clienteId && cotacao.user_id) {
      // verifica se já existe um clientes vinculado a este user_id
      const existing = await queryOne(
        `SELECT id FROM clientes WHERE user_id = $1 AND tenant_id = $2 LIMIT 1`,
        [cotacao.user_id, cotacao.tenant_id]
      )
      if (existing) {
        clienteId = existing.id
      } else {
        // cria o registro usando dados do users
        const user = await queryOne(`SELECT * FROM users WHERE id = $1`, [cotacao.user_id])
        if (user) {
          const novo = await execute(
            `INSERT INTO clientes (tenant_id, user_id, nome, email, cpf_cnpj, tipo, created_at, updated_at)
             VALUES ($1,$2,$3,$4,$5,'PF',NOW(),NOW()) RETURNING id`,
            [cotacao.tenant_id, user.id, user.nome, user.email || null, user.cpf || null]
          )
          clienteId = novo.rows[0]?.id || null
        }
      }
    }

    const pedidoResult = await execute(
      `INSERT INTO pedidos
         (tenant_id,cotacao_id,cliente_id,user_id,endereco_id,status,forma_pagto,tipo_entrega,total,desconto,observacao)
       VALUES ($1,$2,$3,$4,$5,'aguardando',$6,$7,$8,$9,$10) RETURNING *`,
      [cotacao.tenant_id, cotacaoId, clienteId, cotacao.user_id,
       endereco_id || null, cotacao.forma_pagto, tipo_entrega || 'retirada',
       cotacao.total, cotacao.desconto, observacao || cotacao.observacao]
    )
    const pedido = pedidoResult.rows[0]
    if (!pedido) throw new Error('Falha ao criar pedido')

    for (const item of itens) {
      await execute(
        `INSERT INTO pedido_itens (pedido_id,produto_id,nome_produto,sku,quantidade,preco_unitario,desconto_pct,subtotal,observacao)
         VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)`,
        [pedido.id, item.produto_id, item.nome_produto, item.sku,
         item.quantidade, item.preco_unitario, item.desconto_pct, item.subtotal, item.observacao || null]
      )
    }

    // WPP-10 — gera protocolo único por pedido
    const dt = new Date()
    const yyyymmdd = `${dt.getFullYear()}${String(dt.getMonth()+1).padStart(2,'0')}${String(dt.getDate()).padStart(2,'0')}`
    const protocolo = `PED-${yyyymmdd}-${pedido.id}`
    await execute(`UPDATE pedidos SET protocolo=$1 WHERE id=$2`, [protocolo, pedido.id])

    await execute(
      `UPDATE cotacoes SET status='finalizada', updated_at=NOW() WHERE id=$1`,
      [cotacaoId]
    )
    return { ...pedido, protocolo }
  }
}

module.exports = Cotacao
