'use strict'

const BenefitClub   = require('../models/BenefitClub')
const ClubMember    = require('../models/ClubMember')
const ClubPayment   = require('../models/ClubPayment')
const ClubPartner   = require('../models/ClubPartner')
const ClubAsaas     = require('../services/clubAsaasService')
const ClubNotif     = require('../services/clubNotificationService')
const { execute, queryOne, query } = require('../database/postgres')

function validateCPF(cpf) {
  cpf = cpf.replace(/[^\d]+/g, '')
  if (cpf.length !== 11 || /^(\d)\1{10}$/.test(cpf)) return false
  let sum = 0
  for (let i = 0; i < 9; i++) sum += parseInt(cpf.charAt(i)) * (10 - i)
  let rem = 11 - (sum % 11); if (rem >= 10) rem = 0
  if (rem !== parseInt(cpf.charAt(9))) return false
  sum = 0
  for (let i = 0; i < 10; i++) sum += parseInt(cpf.charAt(i)) * (11 - i)
  rem = 11 - (sum % 11); if (rem >= 10) rem = 0
  return rem === parseInt(cpf.charAt(10))
}

// Formata próxima data de cobrança (hoje + 1 mês)
function nextBillingDate() {
  const d = new Date()
  d.setMonth(d.getMonth() + 1)
  return d.toISOString().slice(0, 10)
}

// ── Público ──────────────────────────────────────────────────────────────────

exports.listClubs = async (req, res) => {
  try {
    const clubs = await BenefitClub.findAll(req.tenant.id)
    for (const c of clubs) {
      c.plans = await BenefitClub.getPlans(c.id)
    }
    res.json(clubs)
  } catch (err) {
    console.error('[clubController] listClubs:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.getClub = async (req, res) => {
  try {
    const club = await BenefitClub.findBySlug(req.params.slug, req.tenant.id)
    if (!club) return res.status(404).json({ error: 'Clube não encontrado' })
    club.plans      = await BenefitClub.getPlans(club.id)
    club.partners   = await ClubPartner.findByClub(club.id)
    // conditions e rules já vêm do findBySlug (colunas da tabela benefit_clubs)
    res.json(club)
  } catch (err) {
    console.error('[clubController] getClub:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Assinatura ────────────────────────────────────────────────────────────────

exports.subscribe = async (req, res) => {
  try {
    const { slug }  = req.params
    const { plan_id, user_cpf, user_nome, user_telefone, user_email } = req.body

    if (!plan_id || !user_cpf || !user_nome)
      return res.status(400).json({ error: 'Campos obrigatórios: plan_id, user_cpf, user_nome' })

    if (!validateCPF(user_cpf)) return res.status(400).json({ error: 'CPF inválido' })

    const club = await BenefitClub.findBySlug(slug, req.tenant.id)
    if (!club) return res.status(404).json({ error: 'Clube não encontrado' })

    const plan = await BenefitClub.getPlanById(plan_id)
    if (!plan || plan.club_id !== club.id)
      return res.status(404).json({ error: 'Plano não encontrado' })

    // Bloqueia apenas se já há assinatura ativa — suspended/pending_payment podem reinscrever
    const existing = await ClubMember.findByCpfAndClub(user_cpf, club.id)
    if (existing?.status === 'active') return res.status(409).json({ error: 'CPF já possui assinatura ativa neste clube' })

    // Cria membro com status pending_payment
    const memberResult = await ClubMember.create({
      tenant_id: req.tenant.id,
      club_id:   club.id,
      plan_id,
      user_cpf,
      user_nome,
      user_telefone: user_telefone || null,
      user_email:    user_email    || null,
      asaas_customer_id:      null,
      asaas_subscription_id:  null,
      next_billing_at:        null,
    })
    const memberId = memberResult.rows?.[0]?.id

    // Cria cliente + assinatura no Asaas em background (não bloqueia resposta)
    const tenantAsaasKey = req.tenant?.asaas_key || process.env.ASAAS_API_KEY
    setImmediate(async () => {
      try {
        const customer = await ClubAsaas.createCustomer({
          cpf: user_cpf, name: user_nome, phone: user_telefone, email: user_email,
          apiKey: tenantAsaasKey,
        })
        const subscription = await ClubAsaas.createSubscription({
          customerId:  customer.id,
          value:       plan.price_monthly,
          description: `${club.name} — ${plan.name}`,
          nextDueDate: nextBillingDate(),
          apiKey:      tenantAsaasKey,
        })
        await ClubMember.updateSubscription(memberId, {
          asaas_customer_id:     customer.id,
          asaas_subscription_id: subscription.id,
          next_billing_at:       subscription.nextDueDate,
        })
      } catch (e) {
        console.error('[clubController] Asaas subscribe error:', e.message)
      }
    })

    // Notificação de boas-vindas
    ClubNotif.notifyWelcome(user_cpf, user_nome, user_telefone, club.name, plan.name, req.tenant?.id)
      .catch(() => {})

    res.status(201).json({ ok: true, member_id: memberId })
  } catch (err) {
    console.error('[clubController] subscribe:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Validação pública (recepção de clínica) ───────────────────────────────────

exports.validateMember = async (req, res) => {
  try {
    const cpf  = req.params.cpf.replace(/\D/g, '')
    const slug = req.params.slug  // 'odonto' ou 'medico'

    const club = await BenefitClub.findBySlug(slug, req.tenant.id)
    if (!club) return res.status(404).json({ valid: false, error: 'Clube não encontrado' })

    const member = await ClubMember.findByCpfAndClub(cpf, club.id)
    if (!member) return res.json({ valid: false, message: 'CPF não encontrado neste clube' })

    if (member.status !== 'active') {
      return res.json({
        valid: false,
        message: `Plano ${member.status === 'suspended' ? 'suspenso por inadimplência' : 'inativo'}`,
        status: member.status,
      })
    }

    res.json({
      valid:       true,
      user_nome:   member.user_nome,
      user_cpf:    cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4'),
      plan_name:   member.plan_name,
      club_name:   club.name,
      next_billing: member.next_billing_at,
      status:      member.status,
    })
  } catch (err) {
    console.error('[clubController] validateMember:', err.message)
    res.status(500).json({ valid: false, error: 'Erro interno' })
  }
}

// ── Parceiros por slug ────────────────────────────────────────────────────────

exports.listPartnersBySlug = async (req, res) => {
  try {
    const club = await BenefitClub.findBySlug(req.params.slug, req.tenant.id)
    if (!club) return res.status(404).json({ error: 'Clube não encontrado' })
    const partners = await ClubPartner.findByClub(club.id)
    res.json(partners || [])
  } catch (err) {
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Carteirinha ───────────────────────────────────────────────────────────────

exports.getCard = async (req, res) => {
  try {
    const cpf = req.params.cpf.replace(/\D/g, '')
    if (!validateCPF(cpf)) return res.status(400).json({ error: 'CPF inválido' })
    const members = await ClubMember.findAllByCpf(cpf)
    if (!members?.length) return res.json([])
    res.json(members)
  } catch (err) {
    console.error('[clubController] getCard:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Cancelamento ──────────────────────────────────────────────────────────────

exports.cancelMembership = async (req, res) => {
  try {
    const user = req.user
    const { member_id } = req.body
    const member = await ClubMember.findById(member_id)
    if (!member) return res.status(404).json({ error: 'Assinatura não encontrada' })
    if (member.user_cpf !== user.cpf?.replace(/\D/g, ''))
      return res.status(403).json({ error: 'Acesso negado' })

    if (member.asaas_subscription_id) {
      await ClubAsaas.cancelSubscription(member.asaas_subscription_id).catch(console.error)
    }
    await ClubMember.updateStatus(member_id, 'canceled')
    res.json({ ok: true })
  } catch (err) {
    console.error('[clubController] cancelMembership:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Admin ─────────────────────────────────────────────────────────────────────

exports.adminListMembers = async (req, res) => {
  try {
    const { club_id, status, limit = 100, offset = 0 } = req.query
    if (!club_id) return res.status(400).json({ error: 'club_id obrigatório' })
    const members = await ClubMember.listByClub(club_id, { status, limit: +limit, offset: +offset })
    res.json(members)
  } catch (err) {
    console.error('[clubController] adminListMembers:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminUpdateMemberStatus = async (req, res) => {
  try {
    const { id }     = req.params
    const { status } = req.body
    const allowed    = ['active', 'suspended', 'canceled', 'pending_payment']
    if (!allowed.includes(status))
      return res.status(400).json({ error: 'Status inválido' })

    const member = await ClubMember.findById(id)
    if (!member) return res.status(404).json({ error: 'Membro não encontrado' })

    // Sincroniza no Asaas se houver assinatura
    if (member.asaas_subscription_id) {
      if (status === 'canceled')
        await ClubAsaas.cancelSubscription(member.asaas_subscription_id).catch(console.error)
      else if (status === 'suspended')
        await ClubAsaas.suspendSubscription(member.asaas_subscription_id).catch(console.error)
      else if (status === 'active' && member.status === 'suspended')
        await ClubAsaas.reactivateSubscription(member.asaas_subscription_id).catch(console.error)
    }

    await ClubMember.updateStatus(id, status)
    res.json({ ok: true })
  } catch (err) {
    console.error('[clubController] adminUpdateMemberStatus:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminListPartners = async (req, res) => {
  try {
    const { club_id } = req.query
    if (!club_id) return res.status(400).json({ error: 'club_id obrigatório' })
    res.json(await ClubPartner.findByClub(club_id))
  } catch (err) {
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminCreatePartner = async (req, res) => {
  try {
    const result = await ClubPartner.create({ ...req.body, tenant_id: req.tenant.id })
    res.status(201).json({ id: result.rows?.[0]?.id })
  } catch (err) {
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminUpdatePartner = async (req, res) => {
  try {
    await ClubPartner.update(req.params.id, req.body)
    res.json({ ok: true })
  } catch (err) {
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminDeletePartner = async (req, res) => {
  try {
    await ClubPartner.delete(req.params.id)
    res.json({ ok: true })
  } catch (err) {
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Admin — Planos ────────────────────────────────────────────────────────────

exports.adminListPlans = async (req, res) => {
  try {
    const { club_id } = req.query
    if (!club_id) return res.status(400).json({ error: 'club_id obrigatório' })
    const plans = await query(
      `SELECT * FROM club_plans WHERE club_id=$1 ORDER BY id ASC`,
      [club_id]
    )
    res.json(plans || [])
  } catch (err) {
    console.error('[clubController] adminListPlans:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminCreatePlan = async (req, res) => {
  try {
    const { club_id, name, description, price_monthly, max_dependents, features } = req.body
    if (!club_id || !name || price_monthly == null)
      return res.status(400).json({ error: 'Campos obrigatórios: club_id, name, price_monthly' })
    const result = await execute(
      `INSERT INTO club_plans (club_id, name, description, price_monthly, max_dependents, features)
       VALUES ($1,$2,$3,$4,$5,$6) RETURNING id`,
      [club_id, name, description || null, price_monthly, max_dependents || 0, JSON.stringify(features || [])]
    )
    res.status(201).json({ id: result.rows?.[0]?.id })
  } catch (err) {
    console.error('[clubController] adminCreatePlan:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminUpdatePlan = async (req, res) => {
  try {
    const { id } = req.params
    const { name, description, price_monthly, max_dependents, features, active } = req.body
    await execute(
      `UPDATE club_plans SET
         name=$1, description=$2, price_monthly=$3, max_dependents=$4, features=$5, active=$6
       WHERE id=$7`,
      [name, description || null, price_monthly, max_dependents ?? 0, JSON.stringify(features || []), active ?? true, id]
    )
    res.json({ ok: true })
  } catch (err) {
    console.error('[clubController] adminUpdatePlan:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminDeletePlan = async (req, res) => {
  try {
    const { id } = req.params
    // Verifica se há membros ativos neste plano
    const active = await queryOne(
      `SELECT id FROM club_members WHERE plan_id=$1 AND status IN ('active','pending_payment','suspended') LIMIT 1`,
      [id]
    )
    if (active) return res.status(409).json({ error: 'Plano possui membros ativos. Desative-o primeiro.' })
    await execute(`DELETE FROM club_plans WHERE id=$1`, [id])
    res.json({ ok: true })
  } catch (err) {
    console.error('[clubController] adminDeletePlan:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Admin — Conteúdo (condições + regras) ────────────────────────────────────

exports.adminSaveContent = async (req, res) => {
  try {
    const { id } = req.params
    const tid = req.tenant?.id || req.admin?.tenant_id
    const { conditions, rules } = req.body
    const result = await execute(
      `UPDATE benefit_clubs SET conditions=$1, rules=$2 WHERE id=$3 AND tenant_id=$4`,
      [conditions || null, rules || null, id, tid]
    )
    if (result.rowCount === 0) return res.status(404).json({ error: 'Clube não encontrado' })
    res.json({ ok: true })
  } catch (err) {
    console.error('[clubController] adminSaveContent:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Public — FAQs por slug ────────────────────────────────────────────────────

exports.listFaqsBySlug = async (req, res) => {
  try {
    const club = await BenefitClub.findBySlug(req.params.slug, req.tenant.id)
    if (!club) return res.status(404).json({ error: 'Clube não encontrado' })
    const faqs = await query(
      `SELECT id, question, answer, sort_order FROM club_faqs
       WHERE club_id=$1 AND active=true ORDER BY sort_order ASC, id ASC`,
      [club.id]
    )
    res.json(faqs || [])
  } catch (err) {
    console.error('[clubController] listFaqsBySlug:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Admin — FAQs ─────────────────────────────────────────────────────────────

exports.adminListFaqs = async (req, res) => {
  try {
    const { club_id } = req.query
    if (!club_id) return res.status(400).json({ error: 'club_id obrigatório' })
    const faqs = await query(
      `SELECT * FROM club_faqs WHERE club_id=$1 ORDER BY sort_order ASC, id ASC`,
      [club_id]
    )
    res.json(faqs || [])
  } catch (err) {
    console.error('[clubController] adminListFaqs:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminCreateFaq = async (req, res) => {
  try {
    const { club_id, question, answer, sort_order, active } = req.body
    if (!club_id || !question || !answer)
      return res.status(400).json({ error: 'Campos obrigatórios: club_id, question, answer' })
    const result = await execute(
      `INSERT INTO club_faqs (club_id, tenant_id, question, answer, sort_order, active)
       VALUES ($1,$2,$3,$4,$5,$6) RETURNING id`,
      [club_id, req.tenant.id, question, answer, sort_order ?? 0, active ?? true]
    )
    res.status(201).json({ id: result.rows?.[0]?.id })
  } catch (err) {
    console.error('[clubController] adminCreateFaq:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminUpdateFaq = async (req, res) => {
  try {
    const { id } = req.params
    const { question, answer, sort_order, active } = req.body
    await execute(
      `UPDATE club_faqs SET question=$1, answer=$2, sort_order=$3, active=$4 WHERE id=$5`,
      [question, answer, sort_order ?? 0, active ?? true, id]
    )
    res.json({ ok: true })
  } catch (err) {
    console.error('[clubController] adminUpdateFaq:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

exports.adminDeleteFaq = async (req, res) => {
  try {
    await execute(`DELETE FROM club_faqs WHERE id=$1`, [req.params.id])
    res.json({ ok: true })
  } catch (err) {
    console.error('[clubController] adminDeleteFaq:', err.message)
    res.status(500).json({ error: 'Erro interno' })
  }
}

// ── Webhook Asaas (clube) ─────────────────────────────────────────────────────

const ASAAS_WEBHOOK_TOKEN = process.env.ASAAS_WEBHOOK_TOKEN

exports.asaasClubWebhook = async (req, res) => {
  try {
    if (!ASAAS_WEBHOOK_TOKEN) {
      console.error('[clubController] ASAAS_WEBHOOK_TOKEN não configurado')
      return res.status(500).json({ error: 'Configuração incompleta' })
    }
    const incomingToken = req.headers['asaas-access-token']
    if (!incomingToken || incomingToken !== ASAAS_WEBHOOK_TOKEN) {
      console.warn('[clubController] asaasClubWebhook: token inválido rejeitado')
      return res.status(401).json({ error: 'Não autorizado' })
    }

    const { event, payment } = req.body
    if (!payment?.subscription) return res.sendStatus(200)

    const member = await ClubMember.findBySubscriptionId(payment.subscription)
    if (!member) return res.sendStatus(200)

    if (event === 'PAYMENT_RECEIVED' || event === 'PAYMENT_CONFIRMED') {
      await ClubMember.updateStatus(member.id, 'active')
      await ClubPayment.create({
        member_id:        member.id,
        plan_id:          member.plan_id,
        amount:           payment.value,
        status:           'paid',
        asaas_payment_id: payment.id,
        reference_month:  payment.dueDate?.slice(0, 7) || null,
      })
      // Atualiza próxima cobrança
      if (payment.billingType) {
        await ClubMember.updateSubscription(member.id, {
          asaas_subscription_id: member.asaas_subscription_id,
          asaas_customer_id:     member.asaas_customer_id,
          next_billing_at:       payment.originalDueDate || null,
        })
      }
      ClubNotif.notifyPaymentConfirmed(
        member.user_cpf, member.user_nome, member.user_telefone, member.club_name, member.tenant_id
      ).catch(() => {})
    }

    if (event === 'PAYMENT_OVERDUE') {
      await ClubMember.updateStatus(member.id, 'suspended')
      ClubNotif.notifyPaymentOverdue(
        member.user_cpf, member.user_nome, member.user_telefone, member.club_name, member.tenant_id
      ).catch(() => {})
    }

    if (event === 'PAYMENT_DELETED' || event === 'SUBSCRIPTION_DELETED') {
      await ClubMember.updateStatus(member.id, 'canceled')
    }

    res.sendStatus(200)
  } catch (err) {
    console.error('[clubController] asaasClubWebhook:', err.message)
    res.sendStatus(500)
  }
}
