import { Router, Request, Response } from 'express';
import { db, Subscriber } from '../../database/db';
import { NetworkDriverFactory } from '../network/driver.factory';
import { SubscriberDTO } from '../network/driver.interface';

const router = Router();

// GET /api/subscribers - List subscribers with package and ONU details
router.get('/', (req: Request, res: Response) => {
  const { reseller_id, search, status, driver_type } = req.query;

  let subs = [...db.subscribers];

  if (reseller_id) {
    subs = subs.filter(s => s.reseller_id === reseller_id);
  }
  if (status) {
    subs = subs.filter(s => s.status === status);
  }
  if (driver_type) {
    subs = subs.filter(s => s.driver_type === driver_type);
  }
  if (search) {
    const q = String(search).toLowerCase();
    subs = subs.filter(
      s => s.username.toLowerCase().includes(q) || s.full_name.toLowerCase().includes(q) || s.phone.includes(q)
    );
  }

  const enriched = subs.map(s => {
    const pkg = db.packages.find(p => p.id === s.package_id);
    const onu = s.onu_id ? db.onus.find(o => o.id === s.onu_id) : undefined;
    const reseller = s.reseller_id ? db.resellers.find(r => r.id === s.reseller_id) : undefined;
    return {
      ...s,
      package_name: pkg?.name,
      speed_mbps: pkg?.speed_mbps,
      wholesale_price: pkg?.wholesale_price,
      retail_price: pkg?.default_retail_price,
      reseller_name: reseller?.company_name || 'Direct / Super Admin',
      onu_mac: onu?.mac_serial,
      onu_rx_power: onu?.rx_power_dbm,
      onu_laser_status: onu?.laser_status
    };
  });

  res.json({ success: true, count: enriched.length, data: enriched });
});

// GET /api/subscribers/:id - Get single subscriber
router.get('/:id', (req: Request, res: Response) => {
  const sub = db.subscribers.find(s => s.id === req.params.id || s.username === req.params.id);
  if (!sub) {
    return res.status(404).json({ success: false, message: 'Subscriber not found' });
  }

  const pkg = db.packages.find(p => p.id === sub.package_id);
  const onu = sub.onu_id ? db.onus.find(o => o.id === sub.onu_id) : undefined;
  const invoices = db.invoices.filter(i => i.subscriber_id === sub.id);
  const payments = db.payments.filter(p => p.subscriber_id === sub.id);
  const tickets = db.support_tickets.filter(t => t.subscriber_id === sub.id);

  res.json({
    success: true,
    data: {
      ...sub,
      package: pkg,
      onu,
      invoices,
      payments,
      tickets
    }
  });
});

// POST /api/subscribers - Create new subscriber & provision on network driver
router.post('/', async (req: Request, res: Response) => {
  try {
    const {
      username,
      password,
      full_name,
      phone,
      email,
      address,
      driver_type = 'MIKROTIK_API',
      package_id,
      reseller_id,
      ip_address,
      mac_address
    } = req.body;

    if (!username || !full_name || !phone || !package_id) {
      return res.status(400).json({ success: false, message: 'Missing required subscriber fields.' });
    }

    if (db.subscribers.some(s => s.username.toLowerCase() === username.toLowerCase())) {
      return res.status(400).json({ success: false, message: `Username '${username}' is already taken.` });
    }

    const pkg = db.packages.find(p => p.id === package_id);
    if (!pkg) {
      return res.status(400).json({ success: false, message: 'Invalid package_id' });
    }

    const now = new Date();
    const expiryDate = new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString();

    const newSub: Subscriber = {
      id: `sub_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,
      tenant_id: 'tenant_main',
      reseller_id: reseller_id || undefined,
      username,
      password_hash: password || 'pass1234',
      full_name,
      phone,
      email,
      address,
      driver_type,
      package_id,
      ip_address: ip_address || `10.10.20.${Math.floor(100 + Math.random() * 150)}`,
      mac_address: mac_address || '00:1A:2B:3C:4D:EE',
      connection_type: 'PPPOE',
      status: 'active',
      expiration_date: expiryDate,
      fup_used_bytes: 0,
      created_at: now.toISOString(),
      updated_at: now.toISOString()
    };

    db.subscribers.unshift(newSub);

    // Provision on Network Driver
    const subscriberDTO: SubscriberDTO = {
      id: newSub.id,
      username: newSub.username,
      password: password || 'pass1234',
      driver_type: newSub.driver_type,
      speed_mbps: pkg.speed_mbps,
      mikrotik_profile: pkg.mikrotik_profile_name,
      radius_group: pkg.radius_group_name,
      ip_address: newSub.ip_address,
      mac_address: newSub.mac_address,
      status: 'active'
    };

    const driverResult = await NetworkDriverFactory.executeAction('createUser', subscriberDTO);

    db.persist();

    res.status(201).json({
      success: true,
      message: `Subscriber '${username}' registered and provisioned on ${driver_type}.`,
      data: newSub,
      driverResult
    });
  } catch (err: any) {
    res.status(500).json({ success: false, message: err.message });
  }
});

// POST /api/subscribers/:id/action - Manual driver action (suspend, activate, terminateSession, switchDriver)
router.post('/:id/action', async (req: Request, res: Response) => {
  try {
    const { action, driver_type } = req.body;
    const sub = db.subscribers.find(s => s.id === req.params.id || s.username === req.params.id);

    if (!sub) {
      return res.status(404).json({ success: false, message: 'Subscriber not found' });
    }

    const pkg = db.packages.find(p => p.id === sub.package_id);
    
    if (driver_type && (driver_type === 'MIKROTIK_API' || driver_type === 'RADIUS')) {
      sub.driver_type = driver_type;
    }

    const subscriberDTO: SubscriberDTO = {
      id: sub.id,
      username: sub.username,
      password: sub.password_hash,
      driver_type: sub.driver_type,
      speed_mbps: pkg?.speed_mbps || 20,
      mikrotik_profile: pkg?.mikrotik_profile_name,
      radius_group: pkg?.radius_group_name,
      ip_address: sub.ip_address,
      mac_address: sub.mac_address,
      status: sub.status
    };

    let result;
    if (action === 'suspend') {
      sub.status = 'suspended';
      result = await NetworkDriverFactory.executeAction('suspendUser', subscriberDTO, 'Manual Admin Suspension');
    } else if (action === 'activate') {
      sub.status = 'active';
      result = await NetworkDriverFactory.executeAction('activateUser', subscriberDTO);
    } else if (action === 'terminate_session') {
      result = await NetworkDriverFactory.executeAction('terminateLiveSession', subscriberDTO);
    } else {
      return res.status(400).json({ success: false, message: 'Invalid action requested' });
    }

    sub.updated_at = new Date().toISOString();
    db.persist();

    res.json({
      success: true,
      message: `Action '${action}' executed successfully on ${sub.driver_type}.`,
      data: sub,
      driverResult: result
    });
  } catch (err: any) {
    res.status(500).json({ success: false, message: err.message });
  }
});

// POST /api/subscribers/quick-recharge - 1-Click Bill Recharge for Cash, bKash, Nagad
router.post('/quick-recharge', async (req: Request, res: Response) => {
  try {
    const { username, payment_method = 'MANUAL_CASH', months = 1, amount, collector_name } = req.body;
    if (!username) return res.status(400).json({ success: false, message: 'Username or phone required' });

    const sub = db.subscribers.find(s => s.username === username || s.phone === username || s.id === username);
    if (!sub) return res.status(404).json({ success: false, message: 'Subscriber not found' });

    const pkg = db.packages.find(p => p.id === sub.package_id);
    const rechargeAmount = amount ? Number(amount) : (pkg?.default_retail_price || 600) * Number(months);

    // Renew subscription, extend 30 days, generate tax invoice, and unblock on network driver
    const { BillingService } = await import('../billing/billing.service');
    const { SmsService } = await import('../sms/sms.service');

    const renewal = await BillingService.renewSubscriberSubscription({
      subscriberUsername: sub.username,
      gateway: payment_method as any,
      trxId: `BILL-${Date.now().toString().slice(-6)}-${Math.floor(100 + Math.random() * 900)}`,
      amountReceived: rechargeAmount
    });

    // Send confirmation SMS
    SmsService.sendSms({
      phone: sub.phone,
      subscriberUsername: sub.username,
      templateType: 'PAYMENT_CONFIRM',
      message: `Dear ${sub.full_name}, your internet bill of ৳${rechargeAmount} has been received. Expiry: ${new Date(sub.expiration_date).toLocaleDateString('en-GB')}. Thanks, NexGen ISP.`
    }).catch(() => {});

    res.json({
      success: true,
      message: `Successfully recharged ৳${rechargeAmount} for ${sub.username}. Line activated on MikroTik!`,
      data: renewal
    });
  } catch (err: any) {
    res.status(500).json({ success: false, message: err.message });
  }
});

// PUT /api/subscribers/:id - Edit Subscriber
router.put('/:id', (req: Request, res: Response) => {
  const sub = db.subscribers.find(s => s.id === req.params.id || s.username === req.params.id);
  if (!sub) return res.status(404).json({ success: false, message: 'Subscriber not found' });

  const { full_name, phone, email, address, package_id, driver_type } = req.body;
  if (full_name) sub.full_name = full_name;
  if (phone) sub.phone = phone;
  if (email) sub.email = email;
  if (address) sub.address = address;
  if (package_id) sub.package_id = package_id;
  if (driver_type) sub.driver_type = driver_type;
  sub.updated_at = new Date().toISOString();

  db.logAudit('SUPER_ADMIN', sub.id, 'SUBSCRIBER_UPDATED', req.body);
  db.persist();

  res.json({ success: true, message: `Subscriber ${sub.username} updated.`, data: sub });
});

// DELETE /api/subscribers/:id - Remove Subscriber
router.delete('/:id', (req: Request, res: Response) => {
  const index = db.subscribers.findIndex(s => s.id === req.params.id || s.username === req.params.id);
  if (index === -1) return res.status(404).json({ success: false, message: 'Subscriber not found' });

  const deleted = db.subscribers.splice(index, 1)[0];
  db.logAudit('SUPER_ADMIN', deleted.id, 'SUBSCRIBER_DELETED', { username: deleted.username });
  db.persist();

  res.json({ success: true, message: `Subscriber ${deleted.username} deleted.` });
});

export const subscriberRouter = router;
