'use strict'

const Cliente = require('../models/Cliente')

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

function validarCnpj(cnpj) {
  cnpj = cnpj.replace(/\D/g, '')
  if (cnpj.length !== 14 || /^(\d)\1+$/.test(cnpj)) return false
  const calc = (n) => {
    let s = 0, p = n - 7
    for (let i = 0; i < n; i++) { p = p < 2 ? p + 9 : p; s += +cnpj[i] * p--; }
    return s % 11 < 2 ? 0 : 11 - (s % 11)
  }
  return calc(12) === +cnpj[12] && calc(13) === +cnpj[13]
}

const clienteController = {
  async list(req, res) {
    try {
      const tenantId = req.tenant.id
      const { search, tipo, status, limit, offset } = req.query
      const rows = await Cliente.list(tenantId, { search, tipo, status, limit, offset })
      res.json(rows)
    } catch (err) {
      console.error('[cliente.list]', err.message)
      res.status(500).json({ error: 'Erro ao listar clientes' })
    }
  },

  async get(req, res) {
    try {
      const cliente = await Cliente.findComplete(req.params.id)
      if (!cliente) return res.status(404).json({ error: 'Cliente não encontrado' })
      res.json(cliente)
    } catch (err) {
      console.error('[cliente.get]', err.message)
      res.status(500).json({ error: 'Erro ao buscar cliente' })
    }
  },

  async create(req, res) {
    try {
      const tenantId = req.tenant.id
      const { tipo, nome, cpf_cnpj, email, status } = req.body
      if (!tipo || !['PF', 'PJ'].includes(tipo)) return res.status(400).json({ error: 'tipo deve ser PF ou PJ' })
      if (!nome?.trim()) return res.status(400).json({ error: 'nome é obrigatório' })
      if (!cpf_cnpj?.trim()) return res.status(400).json({ error: 'cpf_cnpj é obrigatório' })

      const doc = cpf_cnpj.replace(/\D/g, '')
      if (tipo === 'PF' && !validarCpf(doc)) return res.status(400).json({ error: 'CPF inválido' })
      if (tipo === 'PJ' && !validarCnpj(doc)) return res.status(400).json({ error: 'CNPJ inválido' })

      const existe = await Cliente.findByCpfCnpj(doc, tenantId)
      if (existe) return res.status(409).json({ error: 'CPF/CNPJ já cadastrado' })

      const user_id = req.user?.id || null
      const cliente = await Cliente.create({ tenant_id: tenantId, tipo, nome: nome.trim(), cpf_cnpj: doc, email, status, user_id })
      res.status(201).json(cliente)
    } catch (err) {
      console.error('[cliente.create]', err.message)
      res.status(500).json({ error: 'Erro ao criar cliente' })
    }
  },

  async update(req, res) {
    try {
      const { nome, email, status } = req.body
      if (!nome?.trim()) return res.status(400).json({ error: 'nome é obrigatório' })
      await Cliente.update(req.params.id, { nome: nome.trim(), email, status })
      res.json({ ok: true })
    } catch (err) {
      console.error('[cliente.update]', err.message)
      res.status(500).json({ error: 'Erro ao atualizar cliente' })
    }
  },

  async remove(req, res) {
    try {
      await Cliente.delete(req.params.id)
      res.json({ ok: true })
    } catch (err) {
      console.error('[cliente.remove]', err.message)
      res.status(500).json({ error: 'Erro ao remover cliente' })
    }
  },

  // ── Endereços ─────────────────────────────────────────────

  async listEnderecos(req, res) {
    try {
      res.json(await Cliente.listEnderecos(req.params.id))
    } catch (err) {
      res.status(500).json({ error: 'Erro ao listar endereços' })
    }
  },

  async addEndereco(req, res) {
    try {
      const dados = { ...req.body, cliente_id: req.params.id }
      const end = await Cliente.createEndereco(dados)
      if (dados.principal) await Cliente.setEndereçoPrincipal(req.params.id, end.id)
      res.status(201).json(end)
    } catch (err) {
      console.error('[cliente.addEndereco]', err.message)
      res.status(500).json({ error: 'Erro ao adicionar endereço' })
    }
  },

  async updateEndereco(req, res) {
    try {
      await Cliente.updateEndereco(req.params.endId, req.body)
      if (req.body.principal) await Cliente.setEndereçoPrincipal(req.params.id, req.params.endId)
      res.json({ ok: true })
    } catch (err) {
      res.status(500).json({ error: 'Erro ao atualizar endereço' })
    }
  },

  async removeEndereco(req, res) {
    try {
      await Cliente.deleteEndereco(req.params.endId)
      res.json({ ok: true })
    } catch (err) {
      res.status(500).json({ error: 'Erro ao remover endereço' })
    }
  },

  // ── Telefones ─────────────────────────────────────────────

  async listTelefones(req, res) {
    try {
      res.json(await Cliente.listTelefones(req.params.id))
    } catch (err) {
      res.status(500).json({ error: 'Erro ao listar telefones' })
    }
  },

  async addTelefone(req, res) {
    try {
      const tel = await Cliente.createTelefone({ ...req.body, cliente_id: req.params.id })
      res.status(201).json(tel)
    } catch (err) {
      res.status(500).json({ error: 'Erro ao adicionar telefone' })
    }
  },

  async updateTelefone(req, res) {
    try {
      await Cliente.updateTelefone(req.params.telId, req.body)
      res.json({ ok: true })
    } catch (err) {
      res.status(500).json({ error: 'Erro ao atualizar telefone' })
    }
  },

  async removeTelefone(req, res) {
    try {
      await Cliente.deleteTelefone(req.params.telId)
      res.json({ ok: true })
    } catch (err) {
      res.status(500).json({ error: 'Erro ao remover telefone' })
    }
  },

  // ── Responsáveis ─────────────────────────────────────────

  async listResponsaveis(req, res) {
    try {
      res.json(await Cliente.listResponsaveis(req.params.id))
    } catch (err) {
      res.status(500).json({ error: 'Erro ao listar responsáveis' })
    }
  },

  async addResponsavel(req, res) {
    try {
      const r = await Cliente.createResponsavel({ ...req.body, cliente_id: req.params.id })
      res.status(201).json(r)
    } catch (err) {
      res.status(500).json({ error: 'Erro ao adicionar responsável' })
    }
  },

  async updateResponsavel(req, res) {
    try {
      await Cliente.updateResponsavel(req.params.respId, req.body)
      res.json({ ok: true })
    } catch (err) {
      res.status(500).json({ error: 'Erro ao atualizar responsável' })
    }
  },

  async removeResponsavel(req, res) {
    try {
      await Cliente.deleteResponsavel(req.params.respId)
      res.json({ ok: true })
    } catch (err) {
      res.status(500).json({ error: 'Erro ao remover responsável' })
    }
  },
}

module.exports = clienteController
