/**
 * Quote Controller
 * Mecánicas Diesel - ERP Suite
 *
 * REST API endpoints for quotations.
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { QuoteService } from '../services/quote.service';
import { QuoteStatus } from '../entities/quote.entity';

interface TenantRequest extends Request {
  tenantId?: string;
  userId?: string;
}

export function createQuoteController(dataSource: DataSource): Router {
  const router = Router();
  const service = new QuoteService(dataSource);

  const extractTenant = (req: TenantRequest, res: Response, next: NextFunction) => {
    const tenantId = req.headers['x-tenant-id'] as string;
    if (!tenantId) {
      return res.status(400).json({ error: 'Tenant ID is required' });
    }
    req.tenantId = tenantId;
    req.userId = req.headers['x-user-id'] as string;
    next();
  };

  router.use(extractTenant);

  /**
   * Create a new quote
   * POST /api/quotes
   */
  router.post('/', async (req: TenantRequest, res: Response) => {
    try {
      const quote = await service.create(req.tenantId!, req.body, req.userId);
      res.status(201).json(quote);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * List quotes with filters
   * GET /api/quotes
   */
  router.get('/', async (req: TenantRequest, res: Response) => {
    try {
      const filters = {
        status: req.query.status as QuoteStatus,
        customerId: req.query.customerId as string,
        vehicleId: req.query.vehicleId as string,
        fromDate: req.query.fromDate ? new Date(req.query.fromDate as string) : undefined,
        toDate: req.query.toDate ? new Date(req.query.toDate as string) : undefined,
      };

      const pagination = {
        page: parseInt(req.query.page as string, 10) || 1,
        limit: Math.min(parseInt(req.query.limit as string, 10) || 20, 100),
      };

      const result = await service.findAll(req.tenantId!, filters, pagination);
      res.json(result);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get quote statistics
   * GET /api/quotes/stats
   */
  router.get('/stats', async (req: TenantRequest, res: Response) => {
    try {
      const stats = await service.getStats(req.tenantId!);
      res.json(stats);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Update expired quotes
   * POST /api/quotes/update-expired
   */
  router.post('/update-expired', async (req: TenantRequest, res: Response) => {
    try {
      const count = await service.updateExpiredQuotes(req.tenantId!);
      res.json({ updated: count });
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get a single quote
   * GET /api/quotes/:id
   */
  router.get('/:id', async (req: TenantRequest, res: Response) => {
    try {
      const quote = await service.findById(req.tenantId!, req.params.id);
      if (!quote) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.json(quote);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Get by quote number
   * GET /api/quotes/number/:quoteNumber
   */
  router.get('/number/:quoteNumber', async (req: TenantRequest, res: Response) => {
    try {
      const quote = await service.findByNumber(req.tenantId!, req.params.quoteNumber);
      if (!quote) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.json(quote);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Send quote to customer
   * POST /api/quotes/:id/send
   */
  router.post('/:id/send', async (req: TenantRequest, res: Response) => {
    try {
      const channel = req.body.channel || 'email';
      const quote = await service.send(req.tenantId!, req.params.id, channel);
      if (!quote) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.json(quote);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Mark quote as viewed
   * POST /api/quotes/:id/view
   */
  router.post('/:id/view', async (req: TenantRequest, res: Response) => {
    try {
      const quote = await service.markViewed(req.tenantId!, req.params.id);
      if (!quote) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.json(quote);
    } catch (error) {
      res.status(500).json({ error: (error as Error).message });
    }
  });

  /**
   * Approve quote (customer action)
   * POST /api/quotes/:id/approve
   */
  router.post('/:id/approve', async (req: TenantRequest, res: Response) => {
    try {
      const approvalData = {
        approvedByName: req.body.approvedByName,
        approvalSignature: req.body.approvalSignature,
        approvalIp: req.ip,
      };
      const quote = await service.approve(req.tenantId!, req.params.id, approvalData);
      if (!quote) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.json(quote);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Reject quote
   * POST /api/quotes/:id/reject
   */
  router.post('/:id/reject', async (req: TenantRequest, res: Response) => {
    try {
      const quote = await service.reject(req.tenantId!, req.params.id, req.body.reason);
      if (!quote) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.json(quote);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Convert quote to service order
   * POST /api/quotes/:id/convert
   */
  router.post('/:id/convert', async (req: TenantRequest, res: Response) => {
    try {
      const order = await service.convertToOrder(req.tenantId!, req.params.id, req.userId);
      if (!order) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.status(201).json(order);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  /**
   * Apply discount to quote
   * POST /api/quotes/:id/discount
   */
  router.post('/:id/discount', async (req: TenantRequest, res: Response) => {
    try {
      const quote = await service.applyDiscount(req.tenantId!, req.params.id, req.body);
      if (!quote) {
        return res.status(404).json({ error: 'Quote not found' });
      }
      res.json(quote);
    } catch (error) {
      res.status(400).json({ error: (error as Error).message });
    }
  });

  return router;
}
