import { Router, Request, Response } from 'express';
import { PluginContext } from '../../../backend/src/core/types';
import { authenticate } from '../../../backend/src/middleware/auth';
import { authorize } from '../../../backend/src/middleware/rbac';

const STATUS_VALUES = ['new', 'contacted', 'qualified', 'converted', 'lost'];
const LEAD_TYPE_VALUES = ['cold', 'member'];

function translateLead(lead: any) {
    if (!lead) return lead;
    return {
        ...lead,
        source: lead.source || 'manual',
        partner_id: lead.partner_id || null,
        benefit_id: lead.benefit_id || null,
        user_id: lead.user_id || null,
        lead_type: lead.lead_type || 'cold',
    };
}

export function createLeadsRoutes(ctx: PluginContext): Router {
    const router = Router();
    const { db } = ctx;
    const protectedRoutes = [authenticate, authorize(['super_admin', 'admin'])];

    // GET /api/leads/metrics — Global metrics for super admin
    router.get('/metrics', ...protectedRoutes, async (req: Request, res: Response) => {
        try {
            const [totalRow] = await db('leads').count('id as total');
            const total = Number(totalRow.total);

            // Today
            const [todayRow] = await db('leads')
                .count('id as total')
                .whereRaw('DATE(created_at) = CURDATE()');
            const today = Number(todayRow.total);

            // By status
            const byStatus = await db('leads')
                .select('status')
                .count('id as total')
                .groupBy('status');

            // By lead type
            const byType = await db('leads')
                .select('lead_type')
                .count('id as total')
                .groupBy('lead_type');

            // Converted count for conversion rate
            const converted = byStatus.find((r: any) => r.status === 'converted');
            const conversionRate = total > 0 ? ((Number(converted?.total || 0) / total) * 100).toFixed(1) : '0.0';

            // By city (via users join)
            const byCity = await db('leads')
                .join('users', 'leads.user_id', 'users.id')
                .select('users.city', 'users.state')
                .count('leads.id as total')
                .whereNotNull('users.city')
                .groupBy('users.city', 'users.state')
                .orderBy('total', 'desc')
                .limit(10);

            // By neighborhood (via users join)
            const byNeighborhood = await db('leads')
                .join('users', 'leads.user_id', 'users.id')
                .select('users.neighborhood', 'users.city', 'users.state')
                .count('leads.id as total')
                .whereNotNull('users.neighborhood')
                .groupBy('users.neighborhood', 'users.city', 'users.state')
                .orderBy('total', 'desc')
                .limit(10);

            // By partner
            const byPartner = await db('leads')
                .join('partners', 'leads.partner_id', 'partners.id')
                .select('partners.id as partner_id', 'partners.company_name')
                .count('leads.id as total')
                .groupBy('partners.id', 'partners.company_name')
                .orderBy('total', 'desc')
                .limit(10);

            // Recent leads
            const recent = await db('leads')
                .leftJoin('users', 'leads.user_id', 'users.id')
                .leftJoin('partners', 'leads.partner_id', 'partners.id')
                .select(
                    'leads.id',
                    'leads.name',
                    'leads.email',
                    'leads.status',
                    'leads.lead_type',
                    'leads.source',
                    'leads.created_at',
                    'partners.company_name as partner_name',
                    'users.city',
                    'users.neighborhood',
                )
                .orderBy('leads.created_at', 'desc')
                .limit(15);

            res.json({
                total,
                today,
                conversion_rate: conversionRate,
                by_status: byStatus,
                by_type: byType,
                by_city: byCity,
                by_neighborhood: byNeighborhood,
                by_partner: byPartner,
                recent,
            });
        } catch (err: any) {
            console.error('Error fetching lead metrics:', err);
            res.status(500).json({ error: 'Erro ao buscar métricas' });
        }
    });

    router.get('/', authenticate, async (req: Request, res: Response) => {
        try {
            const { partner_id, status, type, page = '1', limit = '20' } = req.query;
            const offset = (parseInt(page as string) - 1) * parseInt(limit as string);
            const userRole = req.user?.role;
            const userPartner = req.user?.partner_id;
            let query = db('leads').orderBy('created_at', 'desc');
            if (partner_id) query = query.where({ partner_id });
            if (userRole === 'partner' && userPartner) {
                query = query.where({ partner_id: userPartner });
            }
            if (type && LEAD_TYPE_VALUES.includes(type as string)) {
                query = query.where({ lead_type: type as string });
            }
            if (status && STATUS_VALUES.includes(status as string)) {
                query = query.where({ status: status as string });
            } else {
                query = query.where({ status: 'new' });
            }

            const countResult = await query.clone().count('id as count');
            const leads = await query.limit(parseInt(limit as string)).offset(offset);
            res.json({ leads: leads.map(translateLead), total: Number(countResult[0].count), page: parseInt(page as string) });
        } catch (err: any) {
            res.status(500).json({ error: 'Erro ao listar leads' });
        }
    });

    router.get('/:id', authenticate, async (req: Request, res: Response) => {
        try {
            const id = Number(req.params.id);
            const lead = await db('leads').where({ id }).first();
            if (!lead) return res.status(404).json({ error: 'Lead não encontrado' });
            if (req.user?.role === 'partner' && req.user.partner_id && lead.partner_id !== req.user.partner_id) {
                return res.status(403).json({ error: 'Acesso negado' });
            }
            const history = await db('lead_history').where({ lead_id: id }).orderBy('created_at', 'desc');
            res.json({ lead: translateLead(lead), history });
        } catch (err: any) {
            res.status(500).json({ error: 'Erro ao buscar lead' });
        }
    });

    router.post('/', ...protectedRoutes, async (req: Request, res: Response) => {
        try {
            const { name, email, phone, partner_id, source, notes, benefit_id, assigned_to, user_id } = req.body;
            const numericUserId = user_id ? Number(user_id) : null;
            const parsedUserId = Number.isInteger(numericUserId) ? numericUserId : null;
            const leadType = parsedUserId ? 'member' : 'cold';
            const [id] = await db('leads').insert({
                name,
                email,
                phone,
                partner_id: partner_id || null,
                benefit_id: benefit_id || null,
                user_id: parsedUserId,
                lead_type: leadType,
                source: source || 'manual',
                notes: notes || null,
                assigned_to: assigned_to || null,
                status: 'new',
                owner: 'clube67',
            });
            await db('lead_history').insert({
                lead_id: id,
                action: 'created',
                new_value: 'new',
                created_by: (req as any).user?.id || null,
            });
            await ctx.hooks.emit('lead:created', { id, email, partner_id });
            const lead = await db('leads').where({ id }).first();
            res.status(201).json(translateLead(lead));
        } catch (err: any) {
            res.status(500).json({ error: 'Erro ao criar lead' });
        }
    });

    router.patch('/:id/status', ...protectedRoutes, async (req: Request, res: Response) => {
        try {
            const id = Number(req.params.id);
            const { status } = req.body;
            if (!STATUS_VALUES.includes(status)) return res.status(400).json({ error: 'Status inválido' });
            const lead = await db('leads').where({ id }).first();
            if (!lead) return res.status(404).json({ error: 'Lead não encontrado' });
            await db('leads').where({ id }).update({ status, updated_at: db.fn.now() });
            await db('lead_history').insert({
                lead_id: id,
                action: 'status',
                old_value: lead.status,
                new_value: status,
                created_by: (req as any).user?.id || null,
            });
            if (status === 'converted') await ctx.hooks.emit('lead:converted', { id });
            if (status === 'lost') await ctx.hooks.emit('lead:lost', { id });
            const updated = await db('leads').where({ id }).first();
            res.json(translateLead(updated));
        } catch (err: any) {
            res.status(500).json({ error: 'Erro ao atualizar status' });
        }
    });

    router.post('/:id/notes', ...protectedRoutes, async (req: Request, res: Response) => {
        try {
            const id = Number(req.params.id);
            const { note } = req.body;
            if (!note) return res.status(400).json({ error: 'Nota obrigatória' });
            const lead = await db('leads').where({ id }).first();
            if (!lead) return res.status(404).json({ error: 'Lead não encontrado' });
            await db('lead_history').insert({
                lead_id: id,
                action: 'note',
                old_value: lead.notes,
                new_value: lead.notes ? `${lead.notes}\n${note}` : note,
                note,
                created_by: (req as any).user?.id || null,
            });
            await db('leads').where({ id }).update({
                notes: db.raw('CONCAT(COALESCE(notes,""), "\n", ?)', [note]),
                updated_at: db.fn.now(),
            });
            const updated = await db('leads').where({ id }).first();
            res.json(translateLead(updated));
        } catch (err: any) {
            res.status(500).json({ error: 'Erro ao salvar nota' });
        }
    });

    return router;
}
