/**
 * Investor Routes
 *
 * Investor CRM with pipeline stages, activity tracking, and AI email generation.
 */

import express, { Request, Response } from 'express';
import { body, validationResult } from 'express-validator';
import { getModels } from '../models';
import { authenticateJwtOrApiToken } from '../middleware/dualAuth';
import { requirePermission } from '../middleware/permissions';

const router = express.Router();

router.use(authenticateJwtOrApiToken);

// Get all investors for a company
router.get('/:companyId', async (req: Request, res: Response) => {
  try {
    const { companyId } = req.params;
    const { Investor } = getModels();

    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const investors = await Investor.find({ companyId }).sort({ createdAt: -1 });
    res.json(investors);
  } catch (error) {
    res.status(500).json({ error: 'Failed to get investors' });
  }
});

// Get pipeline (grouped by stage)
router.get('/pipeline/:companyId', async (req: Request, res: Response) => {
  try {
    const { companyId } = req.params;
    const { Investor } = getModels();

    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const investors = await Investor.find({ companyId });

    // Group by stage
    const pipeline = {
      prospect: investors.filter((i: any) => i.stage === 'prospect'),
      introduced: investors.filter((i: any) => i.stage === 'introduced'),
      meeting: investors.filter((i: any) => i.stage === 'meeting'),
      'due-diligence': investors.filter((i: any) => i.stage === 'due-diligence'),
      'term-sheet': investors.filter((i: any) => i.stage === 'term-sheet'),
      closed: investors.filter((i: any) => i.stage === 'closed'),
      passed: investors.filter((i: any) => i.stage === 'passed'),
    };

    res.json(pipeline);
  } catch (error) {
    res.status(500).json({ error: 'Failed to get pipeline' });
  }
});

// Get single investor
router.get('/detail/:id', async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Investor } = getModels();

    const investor = await Investor.findById(id);
    if (!investor) {
      res.status(404).json({ error: 'Investor not found' });
      return;
    }

    if (!req.user!.companyIds.includes(investor.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    res.json(investor);
  } catch (error) {
    res.status(500).json({ error: 'Failed to get investor' });
  }
});

// Create investor
router.post(
  '/',
  requirePermission('funding', 'create'),
  [
    body('name').trim().notEmpty().withMessage('Investor name is required'),
    body('companyId').notEmpty().withMessage('Company ID is required'),
    body('type').isIn(['angel', 'seed-fund', 'vc', 'private-equity', 'strategic', 'accelerator', 'family-office']).withMessage('Invalid investor type'),
    body('email').isEmail().withMessage('Valid email is required'),
  ],
  async (req: Request, res: Response) => {
    try {
      const errors = validationResult(req);
      if (!errors.isEmpty()) {
        res.status(400).json({ errors: errors.array() });
        return;
      }

      if (!req.user!.companyIds.includes(req.body.companyId) && req.user!.role !== 'admin') {
        res.status(403).json({ error: 'Access denied' });
        return;
      }

      const { Investor } = getModels();
      const cleanBody = Object.fromEntries(
        Object.entries(req.body).filter(([, v]) => v !== '')
      );
      const investor = new Investor({ ...cleanBody, createdBy: req.user!._id });
      await investor.save();

      res.status(201).json(investor);
    } catch (error: any) {
      console.error('[Investor Create Error]', error?.message || error);
      if (error?.name === 'ValidationError') {
        const messages = Object.values(error.errors).map((e: any) => e.message);
        res.status(400).json({ error: messages.join('. '), details: error?.message });
        return;
      }
      res.status(500).json({ error: 'Failed to create investor', details: error?.message });
    }
  }
);

// Update investor
router.put('/:id', requirePermission('funding', 'edit'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Investor } = getModels();

    const investor = await Investor.findById(id);
    if (!investor) {
      res.status(404).json({ error: 'Investor not found' });
      return;
    }

    if (!req.user!.companyIds.includes(investor.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const cleanBody = Object.fromEntries(
      Object.entries(req.body).filter(([, v]) => v !== '')
    );
    Object.assign(investor, cleanBody, { updatedAt: new Date() });
    await investor.save();

    res.json(investor);
  } catch (error: any) {
    console.error('[Investor Update Error]', error?.message || error);
    res.status(500).json({ error: 'Failed to update investor', details: error?.message });
  }
});

// Delete investor
router.delete('/:id', requirePermission('funding', 'delete'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Investor } = getModels();

    const investor = await Investor.findById(id);
    if (!investor) {
      res.status(404).json({ error: 'Investor not found' });
      return;
    }

    if (!req.user!.companyIds.includes(investor.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    await Investor.findByIdAndDelete(id);
    res.json({ message: 'Investor deleted successfully' });
  } catch (error) {
    res.status(500).json({ error: 'Failed to delete investor' });
  }
});

// Update investor stage
router.put('/:id/stage', requirePermission('funding', 'edit'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { stage } = req.body;
    const { Investor } = getModels();

    const investor = await Investor.findById(id);
    if (!investor) {
      res.status(404).json({ error: 'Investor not found' });
      return;
    }

    if (!req.user!.companyIds.includes(investor.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    investor.stage = stage;
    investor.updatedAt = new Date();
    await investor.save();

    res.json(investor);
  } catch (error) {
    res.status(500).json({ error: 'Failed to update stage' });
  }
});

// Add interaction
router.post('/:id/interactions', requirePermission('funding', 'create'), async (req: Request, res: Response) => {
  try {
    const { id } = req.params;
    const { Investor } = getModels();

    const investor = await Investor.findById(id);
    if (!investor) {
      res.status(404).json({ error: 'Investor not found' });
      return;
    }

    if (!req.user!.companyIds.includes(investor.companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    investor.interactions.push({
      ...req.body,
      id: `interaction-${Date.now()}`,
    });
    investor.lastContactDate = new Date().toISOString().split('T')[0];
    investor.updatedAt = new Date();
    await investor.save();

    res.json(investor);
  } catch (error) {
    res.status(500).json({ error: 'Failed to add interaction' });
  }
});

// Get pipeline stats
router.get('/stats/:companyId', async (req: Request, res: Response) => {
  try {
    const { companyId } = req.params;
    const { Investor } = getModels();

    if (!req.user!.companyIds.includes(companyId) && req.user!.role !== 'admin') {
      res.status(403).json({ error: 'Access denied' });
      return;
    }

    const investors = await Investor.find({ companyId });

    const stats = {
      total: investors.length,
      byStage: {
        prospect: investors.filter((i: any) => i.stage === 'prospect').length,
        introduced: investors.filter((i: any) => i.stage === 'introduced').length,
        meeting: investors.filter((i: any) => i.stage === 'meeting').length,
        'due-diligence': investors.filter((i: any) => i.stage === 'due-diligence').length,
        'term-sheet': investors.filter((i: any) => i.stage === 'term-sheet').length,
        closed: investors.filter((i: any) => i.stage === 'closed').length,
        passed: investors.filter((i: any) => i.stage === 'passed').length,
      },
      byPriority: {
        high: investors.filter((i: any) => i.priority === 'high').length,
        medium: investors.filter((i: any) => i.priority === 'medium').length,
        low: investors.filter((i: any) => i.priority === 'low').length,
      },
      followUpsDue: investors.filter((i: any) => i.nextFollowUpDate && new Date(i.nextFollowUpDate) <= new Date()).length,
    };

    res.json(stats);
  } catch (error) {
    res.status(500).json({ error: 'Failed to get stats' });
  }
});

export default router;