const express = require('express');
const router = express.Router();
const jwt = require('jsonwebtoken');
const { supabase } = require('../config/supabase');
const Stripe = require('stripe');

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

// JWT-based admin auth middleware
// Verifies Bearer token and checks user role is 'admin'
const adminAuth = async (req, res, next) => {
  try {
    // Check for Bearer token
    const authHeader = req.headers.authorization;
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      return res.status(401).json({ error: 'Unauthorized' });
    }

    const token = authHeader.split(' ')[1];

    // Verify JWT token
    let decoded;
    try {
      decoded = jwt.verify(token, process.env.JWT_SECRET);
    } catch (err) {
      return res.status(401).json({ error: 'Invalid token' });
    }

    // Get user from database and check role
    const { data: user, error } = await supabase
      .from('users')
      .select('id, email, role')
      .eq('id', decoded.userId)
      .single();

    if (error || !user) {
      return res.status(401).json({ error: 'User not found' });
    }

    // Check if user has admin role
    if (user.role !== 'admin') {
      return res.status(403).json({ error: 'Access denied. Admin only.' });
    }

    // Attach user to request
    req.user = user;
    next();
  } catch (error) {
    console.error('Admin auth error:', error);
    return res.status(401).json({ error: 'Unauthorized' });
  }
};

// Apply admin auth to all routes
router.use(adminAuth);

// ============ DASHBOARD STATS ============

/**
 * GET /api/admin/stats
 * Dashboard statistics
 */
router.get('/stats', async (req, res) => {
  try {
    // Get order counts by status
    const { data: orders, error: ordersError } = await supabase
      .from('orders')
      .select('status, created_at');

    if (ordersError) throw ordersError;

    const today = new Date();
    today.setHours(0, 0, 0, 0);

    const stats = {
      orders: {
        total: orders.length,
        today: orders.filter(o => new Date(o.created_at) >= today).length,
        byStatus: {
          paid: orders.filter(o => o.status === 'paid').length,
          preparing: orders.filter(o => o.status === 'preparing').length,
          shipped: orders.filter(o => o.status === 'shipped').length,
          delivered: orders.filter(o => o.status === 'delivered').length,
          installed: orders.filter(o => o.status === 'installed').length
        }
      }
    };

    // Get subscription stats
    const { data: subs } = await supabase
      .from('subscriptions')
      .select('plan, status');

    if (subs) {
      stats.subscriptions = {
        total: subs.length,
        premium: subs.filter(s => s.plan === 'premium' && s.status === 'active').length,
        free: subs.filter(s => s.plan === 'free').length,
        churned: subs.filter(s => s.status === 'canceled').length
      };

      // MRR = active premium subs * $9.99
      stats.mrr = stats.subscriptions.premium * 9.99;
    }

    // Get beneficiary stats
    const { data: beneficiaries } = await supabase
      .from('beneficiaries')
      .select('status');

    if (beneficiaries) {
      stats.beneficiaries = {
        total: beneficiaries.length,
        active: beneficiaries.filter(b => b.status === 'active').length,
        awaitingSensors: beneficiaries.filter(b => b.status === 'awaiting_sensors').length
      };
    }

    res.json(stats);

  } catch (error) {
    console.error('Stats error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============ ORDERS ============

/**
 * POST /api/admin/orders
 * Create a new order manually
 */
router.post('/orders', async (req, res) => {
  try {
    const {
      user_id,
      customer_email,
      customer_name,
      shipping_address,
      total_amount,
      status,
      notes
    } = req.body;

    // Generate order number
    const orderNumber = `ORD-${Date.now().toString(36).toUpperCase()}`;

    const { data: order, error } = await supabase
      .from('orders')
      .insert({
        user_id: user_id || null,
        customer_email: customer_email || null,
        customer_name: customer_name || null,
        shipping_address,
        total_amount: total_amount || 29900,
        status: status || 'paid',
        order_number: orderNumber,
        notes: notes || null,
        created_at: new Date().toISOString(),
        updated_at: new Date().toISOString(),
      })
      .select()
      .single();

    if (error) throw error;

    res.json(order);

  } catch (error) {
    console.error('Create order error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * GET /api/admin/orders
 * List orders with pagination (optimized)
 */
router.get('/orders', async (req, res) => {
  try {
    const { status } = req.query;
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 50;
    const offset = (page - 1) * limit;

    let query = supabase
      .from('orders')
      .select('*', { count: 'exact' })
      .order('created_at', { ascending: false })
      .range(offset, offset + limit - 1);

    if (status) {
      query = query.eq('status', status);
    }

    const { data: orders, error, count: totalCount } = await query;

    if (error) throw error;

    // Get all user IDs from orders
    const userIds = [...new Set((orders || []).map(o => o.user_id).filter(Boolean))];

    // Single query to get all users
    let usersMap = {};
    if (userIds.length > 0) {
      const { data: users } = await supabase
        .from('users')
        .select('id, email')
        .in('id', userIds);

      usersMap = (users || []).reduce((acc, u) => {
        acc[u.id] = u;
        return acc;
      }, {});
    }

    // Combine data
    const result = (orders || []).map(order => ({
      ...order,
      user: usersMap[order.user_id] || null
    }));

    res.json({
      orders: result,
      pagination: {
        page,
        limit,
        total: totalCount || 0,
        pages: Math.ceil((totalCount || 0) / limit)
      }
    });

  } catch (error) {
    console.error('Orders error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * GET /api/admin/orders/:id
 * Get single order details
 */
router.get('/orders/:id', async (req, res) => {
  try {
    const { data: order, error } = await supabase
      .from('orders')
      .select('*')
      .eq('id', req.params.id)
      .single();

    if (error) throw error;
    if (!order) return res.status(404).json({ error: 'Order not found' });

    // Get related data
    let beneficiary = null;
    if (order.beneficiary_id) {
      const { data: b } = await supabase
        .from('users')
        .select('*')
        .eq('id', order.beneficiary_id)
        .single();
      beneficiary = b;
    }

    res.json({ ...order, beneficiary });

  } catch (error) {
    console.error('Order error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * PATCH /api/admin/orders/:id
 * Update order status, add tracking, etc.
 */
router.patch('/orders/:id', async (req, res) => {
  try {
    const { status, tracking_number, carrier, estimated_delivery } = req.body;

    const updates = { updated_at: new Date().toISOString() };

    if (status) {
      updates.status = status;

      // Set timestamps based on status
      if (status === 'shipped') {
        updates.shipped_at = new Date().toISOString();
      } else if (status === 'delivered') {
        updates.delivered_at = new Date().toISOString();
      }
    }

    if (tracking_number) updates.tracking_number = tracking_number;
    if (carrier) updates.carrier = carrier;
    if (estimated_delivery) updates.estimated_delivery = estimated_delivery;

    const { data, error } = await supabase
      .from('orders')
      .update(updates)
      .eq('id', req.params.id)
      .select()
      .single();

    if (error) throw error;

    // TODO: Send email notification when status changes
    if (status === 'shipped') {
      console.log('TODO: Send shipping notification email');
    } else if (status === 'delivered') {
      console.log('TODO: Send delivery notification email');
    }

    res.json(data);

  } catch (error) {
    console.error('Update order error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============ USERS ============

/**
 * GET /api/admin/users
 * List users with pagination and relationships (optimized)
 */
router.get('/users', async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 50;
    const offset = (page - 1) * limit;
    const filter = req.query.filter; // 'beneficiaries', 'caretakers', 'admins'

    // Get all user_access relationships first (for filtering)
    const { data: accessRecords } = await supabase
      .from('user_access')
      .select('beneficiary_id, accessor_id, role');

    // Create lookup sets
    const beneficiaryIds = new Set((accessRecords || []).map(a => a.beneficiary_id));
    const caretakerIds = new Set((accessRecords || []).map(a => a.accessor_id));

    // Build query
    let query = supabase
      .from('users')
      .select('*', { count: 'exact' })
      .order('created_at', { ascending: false });

    // Apply filter if needed
    if (filter === 'admins') {
      query = query.eq('role', 'admin');
    }

    // Get users
    const { data: allUsers, error, count: totalCount } = await query;
    if (error) throw error;

    // Apply client-side filtering for beneficiaries/caretakers
    let filteredUsers = allUsers || [];
    if (filter === 'beneficiaries') {
      filteredUsers = filteredUsers.filter(u => beneficiaryIds.has(u.id));
    } else if (filter === 'caretakers') {
      filteredUsers = filteredUsers.filter(u => caretakerIds.has(u.id));
    }

    // Apply pagination after filtering
    const paginatedUsers = filteredUsers.slice(offset, offset + limit);

    // Create user email lookup
    const userEmailMap = (allUsers || []).reduce((acc, u) => {
      acc[u.id] = u.email;
      return acc;
    }, {});

    // Enrich paginated users with relationship info
    const enrichedUsers = paginatedUsers.map(user => {
      const watches = (accessRecords || [])
        .filter(a => a.accessor_id === user.id)
        .map(a => ({ ...a, beneficiary_email: userEmailMap[a.beneficiary_id] }));

      const watchedBy = (accessRecords || [])
        .filter(a => a.beneficiary_id === user.id)
        .map(a => ({ ...a, accessor_email: userEmailMap[a.accessor_id] }));

      return {
        ...user,
        watches,
        watched_by: watchedBy,
        is_beneficiary: watchedBy.length > 0,
        is_caretaker: watches.length > 0,
      };
    });

    res.json({
      users: enrichedUsers,
      pagination: {
        page,
        limit,
        total: filteredUsers.length,
        pages: Math.ceil(filteredUsers.length / limit)
      }
    });

  } catch (error) {
    console.error('Users error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * GET /api/admin/users/:id
 * Get user with full details: relationships, devices, orders, subscriptions
 */
router.get('/users/:id', async (req, res) => {
  try {
    const { data: user, error: userError } = await supabase
      .from('users')
      .select('*')
      .eq('id', req.params.id)
      .single();

    if (userError) throw userError;
    if (!user) return res.status(404).json({ error: 'User not found' });

    // Get all users for email lookup
    const { data: allUsers } = await supabase
      .from('users')
      .select('id, email, first_name, last_name');

    // Get relationships: who this user watches
    const { data: watchesAccess } = await supabase
      .from('user_access')
      .select('*')
      .eq('accessor_id', req.params.id);

    const watches = (watchesAccess || []).map(a => {
      const beneficiary = allUsers?.find(u => u.id === a.beneficiary_id);
      return { ...a, user: beneficiary };
    });

    // Get relationships: who watches this user
    const { data: watchedByAccess } = await supabase
      .from('user_access')
      .select('*')
      .eq('beneficiary_id', req.params.id);

    const watched_by = (watchedByAccess || []).map(a => {
      const accessor = allUsers?.find(u => u.id === a.accessor_id);
      return { ...a, user: accessor };
    });

    // Get deployments where user is owner
    const { data: deployments } = await supabase
      .from('deployments')
      .select('*')
      .eq('owner_user_id', req.params.id);

    // Get devices from user's deployments
    let devices = [];
    if (deployments && deployments.length > 0) {
      const deploymentIds = deployments.map(d => d.deployment_id);
      const { data: devs } = await supabase
        .from('devices')
        .select('*')
        .in('well_id', deploymentIds);
      devices = devs || [];
    }

    // Get orders
    const { data: orders } = await supabase
      .from('orders')
      .select('*')
      .eq('user_id', req.params.id)
      .order('created_at', { ascending: false });

    // Get subscriptions
    const { data: subscriptions } = await supabase
      .from('subscriptions')
      .select('*')
      .eq('user_id', req.params.id)
      .order('created_at', { ascending: false });

    res.json({
      ...user,
      watches,
      watched_by,
      is_beneficiary: watched_by.length > 0,
      is_caretaker: watches.length > 0,
      deployments: deployments || [],
      devices,
      orders: orders || [],
      subscriptions: subscriptions || []
    });

  } catch (error) {
    console.error('User error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============ SUBSCRIPTIONS ============

/**
 * GET /api/admin/subscriptions
 * List all subscriptions with pagination (optimized)
 */
router.get('/subscriptions', async (req, res) => {
  try {
    const { status, plan } = req.query;
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 50;
    const offset = (page - 1) * limit;

    let query = supabase
      .from('subscriptions')
      .select('*', { count: 'exact' })
      .order('created_at', { ascending: false })
      .range(offset, offset + limit - 1);

    if (status) query = query.eq('status', status);
    if (plan) query = query.eq('plan', plan);

    const { data: subscriptions, error, count: totalCount } = await query;

    if (error) throw error;

    // Get all user IDs from subscriptions
    const userIds = [...new Set((subscriptions || []).map(s => s.user_id).filter(Boolean))];

    // Single query to get all users
    let usersMap = {};
    if (userIds.length > 0) {
      const { data: users } = await supabase
        .from('users')
        .select('id, email')
        .in('id', userIds);

      usersMap = (users || []).reduce((acc, u) => {
        acc[u.id] = u;
        return acc;
      }, {});
    }

    // Combine data
    const result = (subscriptions || []).map(sub => ({
      ...sub,
      user: usersMap[sub.user_id] || null
    }));

    res.json({
      subscriptions: result,
      pagination: {
        page,
        limit,
        total: totalCount || 0,
        pages: Math.ceil((totalCount || 0) / limit)
      }
    });

  } catch (error) {
    console.error('Subscriptions error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============ REFUNDS ============

/**
 * POST /api/admin/refund
 * Process a refund via Stripe
 */
router.post('/refund', async (req, res) => {
  try {
    const { orderId, amount, reason } = req.body;

    // Get order
    const { data: order, error: orderError } = await supabase
      .from('orders')
      .select('*')
      .eq('id', orderId)
      .single();

    if (orderError || !order) {
      return res.status(404).json({ error: 'Order not found' });
    }

    // Get payment intent from Stripe session
    const session = await stripe.checkout.sessions.retrieve(order.stripe_session_id);
    const paymentIntentId = session.payment_intent;

    // Create refund
    const refund = await stripe.refunds.create({
      payment_intent: paymentIntentId,
      amount: amount ? amount : undefined, // Full refund if no amount specified
      reason: reason || 'requested_by_customer'
    });

    // Update order status
    await supabase
      .from('orders')
      .update({
        status: 'canceled',
        updated_at: new Date().toISOString()
      })
      .eq('id', orderId);

    res.json({
      success: true,
      refund: {
        id: refund.id,
        amount: refund.amount / 100,
        status: refund.status
      }
    });

  } catch (error) {
    console.error('Refund error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============ DEPLOYMENTS ============

/**
 * GET /api/admin/deployments
 * List deployments with pagination (optimized - single queries)
 */
router.get('/deployments', async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 50;
    const offset = (page - 1) * limit;

    // Get deployments with count
    const { data: deployments, error, count: totalCount } = await supabase
      .from('deployments')
      .select('*', { count: 'exact' })
      .order('deployment_id', { ascending: false })
      .range(offset, offset + limit - 1);

    if (error) throw error;

    // Get all owner IDs
    const ownerIds = [...new Set((deployments || []).map(d => d.owner_user_id).filter(Boolean))];

    // Single query to get all owners
    let ownersMap = {};
    if (ownerIds.length > 0) {
      const { data: owners } = await supabase
        .from('users')
        .select('id, email, first_name, last_name')
        .in('id', ownerIds);

      ownersMap = (owners || []).reduce((acc, u) => {
        acc[u.id] = u;
        return acc;
      }, {});
    }

    // Get deployment IDs
    const deploymentIds = (deployments || []).map(d => d.deployment_id);

    // Single query to get device counts
    let deviceCounts = {};
    if (deploymentIds.length > 0) {
      const { data: devices } = await supabase
        .from('devices')
        .select('well_id')
        .in('well_id', deploymentIds);

      // Count devices per deployment
      (devices || []).forEach(d => {
        deviceCounts[d.well_id] = (deviceCounts[d.well_id] || 0) + 1;
      });
    }

    // Combine data
    const result = (deployments || []).map(dep => ({
      ...dep,
      owner: ownersMap[dep.owner_user_id] || null,
      device_count: deviceCounts[dep.deployment_id] || 0
    }));

    res.json({
      deployments: result,
      pagination: {
        page,
        limit,
        total: totalCount || 0,
        pages: Math.ceil((totalCount || 0) / limit)
      }
    });

  } catch (error) {
    console.error('Deployments error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * GET /api/admin/deployments/:id
 * Get single deployment with devices, users with access, events
 */
router.get('/deployments/:id', async (req, res) => {
  try {
    const { data: deployment, error } = await supabase
      .from('deployments')
      .select('*')
      .eq('deployment_id', req.params.id)
      .single();

    if (error) throw error;
    if (!deployment) return res.status(404).json({ error: 'Deployment not found' });

    // Get devices for this deployment
    const { data: devices } = await supabase
      .from('devices')
      .select('*')
      .eq('well_id', deployment.deployment_id);

    // Get owner info
    let owner = null;
    if (deployment.owner_user_id) {
      const { data: u } = await supabase
        .from('users')
        .select('id, email, first_name, last_name, phone')
        .eq('id', deployment.owner_user_id)
        .single();
      owner = u;
    }

    // Get all users with access to this deployment's beneficiary
    // First find beneficiary (owner is also beneficiary in most cases)
    let users_with_access = [];
    if (deployment.owner_user_id) {
      const { data: accessRecords } = await supabase
        .from('user_access')
        .select('*')
        .eq('beneficiary_id', deployment.owner_user_id);

      if (accessRecords && accessRecords.length > 0) {
        const accessorIds = accessRecords.map(a => a.accessor_id);
        const { data: accessors } = await supabase
          .from('users')
          .select('id, email, first_name, last_name')
          .in('id', accessorIds);

        users_with_access = accessRecords.map(a => {
          const user = accessors?.find(u => u.id === a.accessor_id);
          return { ...a, user };
        });
      }
    }

    // Get recent events/alerts for this deployment (if events table exists)
    let events = [];
    try {
      const { data: eventsData } = await supabase
        .from('events')
        .select('*')
        .eq('deployment_id', deployment.deployment_id)
        .order('created_at', { ascending: false })
        .limit(20);
      events = eventsData || [];
    } catch (e) {
      // events table might not exist
    }

    res.json({
      ...deployment,
      devices: devices || [],
      owner,
      users_with_access,
      events
    });

  } catch (error) {
    console.error('Deployment error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============ DEVICES ============

/**
 * GET /api/admin/devices
 * List all devices
 */
router.get('/devices', async (req, res) => {
  try {
    const { well_id } = req.query;

    let query = supabase
      .from('devices')
      .select('*')
      .order('device_id', { ascending: false });

    if (well_id) {
      query = query.eq('well_id', parseInt(well_id));
    }

    const { data: devices, error } = await query;

    if (error) throw error;

    res.json({ devices: devices || [] });

  } catch (error) {
    console.error('Devices error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * GET /api/admin/devices/:id
 * Get single device
 */
router.get('/devices/:id', async (req, res) => {
  try {
    const { data: device, error } = await supabase
      .from('devices')
      .select('*')
      .eq('device_id', req.params.id)
      .single();

    if (error) throw error;
    if (!device) return res.status(404).json({ error: 'Device not found' });

    // Get deployment info if exists
    let deployment = null;
    if (device.well_id) {
      const { data: d } = await supabase
        .from('deployments')
        .select('*')
        .eq('deployment_id', device.well_id)
        .single();
      deployment = d;
    }

    res.json({ ...device, deployment });

  } catch (error) {
    console.error('Device error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============ BENEFICIARIES ============

/**
 * GET /api/admin/beneficiaries
 * List all beneficiaries (optimized)
 */
router.get('/beneficiaries', async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const limit = parseInt(req.query.limit) || 50;
    const offset = (page - 1) * limit;

    // Get all users who are beneficiaries (have user_access records where they are beneficiary_id)
    const { data: accessRecords, error } = await supabase
      .from('user_access')
      .select('beneficiary_id')
      .order('granted_at', { ascending: false });

    if (error) throw error;

    // Get unique beneficiary IDs
    const beneficiaryIds = [...new Set((accessRecords || []).map(a => a.beneficiary_id))];

    // Single query to get all beneficiary users
    let beneficiaries = [];
    if (beneficiaryIds.length > 0) {
      const { data: users } = await supabase
        .from('users')
        .select('*')
        .in('id', beneficiaryIds);
      beneficiaries = users || [];
    }

    // Apply pagination
    const paginatedBeneficiaries = beneficiaries.slice(offset, offset + limit);

    res.json({
      beneficiaries: paginatedBeneficiaries,
      pagination: {
        page,
        limit,
        total: beneficiaries.length,
        pages: Math.ceil(beneficiaries.length / limit)
      }
    });

  } catch (error) {
    console.error('Beneficiaries error:', error);
    res.status(500).json({ error: error.message });
  }
});

module.exports = router;
