import { Response } from 'express';
import { Alert } from '../models/Alert';
import { AuthRequest } from '../middleware/auth.middleware';
import mongoose from 'mongoose';
import { syncVCOMAlarmsForProject, getVCOMAlarmsLive as getVCOMAlarmsLiveService } from '../services/vcomAlarmService';

export const getAlerts = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    // Use native MongoDB query to avoid ObjectId casting issues with legacy string userIds
    const db = mongoose.connection.db;
    if (!db) {
      throw new Error('Database connection not established');
    }

    const alertsCollection = db.collection('alerts');
    
    // Build query conditions - only match alerts with valid userId or no userId
    const queryConditions: any[] = [
      { userId: { $exists: false } }, // Global alerts
      { userId: null }, // Also include null userIds
    ];

    // Add user-specific alerts if user is authenticated
    if (req.user?._id) {
      const userId = req.user._id;
      
      // Check if userId is a valid ObjectId
      if (mongoose.Types.ObjectId.isValid(userId)) {
        const userObjectId = (userId as unknown) instanceof mongoose.Types.ObjectId
          ? userId
          : new mongoose.Types.ObjectId(String(userId));
        
        queryConditions.push(
          { userId: userObjectId },
          { userId: userObjectId.toString() } // Also check string version
        );
      } else {
        // If userId is not a valid ObjectId, also check as string
        queryConditions.push({ userId: userId.toString() });
      }
    }

    const alerts = await alertsCollection
      .find({ $or: queryConditions })
      .sort({ createdAt: -1 })
      .limit(100)
      .toArray();

    // Filter out alerts with invalid userId (like "u1" that's not a valid ObjectId)
    // and convert _id to string for consistency
    const formattedAlerts = alerts
      .filter(alert => {
        // Only include alerts with:
        // - No userId (global alerts)
        // - null userId
        // - Valid ObjectId userId that matches current user
        if (!alert.userId || alert.userId === null) {
          return true; // Global alert
        }
        
        // If userId exists, check if it matches current user
        if (req.user?._id) {
          const alertUserIdStr = alert.userId.toString();
          const currentUserIdStr = req.user._id.toString();
          
          // Only include if userId matches current user
          // This filters out invalid userIds like "u1"
          return alertUserIdStr === currentUserIdStr;
        }
        
        // If no user logged in, only return global alerts
        return false;
      })
      .map(alert => {
        // Format createdAt - handle both Date objects and strings
        let createdAtStr: string;
        if (!alert.createdAt) {
          createdAtStr = new Date().toISOString();
        } else if (alert.createdAt instanceof Date) {
          createdAtStr = alert.createdAt.toISOString();
        } else if (typeof alert.createdAt === 'string') {
          // If it's already a string, try to parse and format it
          const date = new Date(alert.createdAt);
          createdAtStr = isNaN(date.getTime()) ? new Date().toISOString() : date.toISOString();
        } else {
          // Fallback for any other type
          createdAtStr = new Date().toISOString();
        }

        return {
          ...alert,
          _id: alert._id.toString(),
          userId: alert.userId ? (alert.userId instanceof mongoose.Types.ObjectId ? alert.userId.toString() : alert.userId.toString()) : undefined,
          createdAt: createdAtStr,
        };
      });

    res.json({
      success: true,
      data: formattedAlerts,
    });
  } catch (error: any) {
    res.status(500).json({
      success: false,
      message: error.message || 'Failed to fetch alerts',
    });
  }
};

export const createAlert = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { type, message, severity, link, userId } = req.body;

    if (!type || !message || !severity) {
      res.status(400).json({
        success: false,
        message: 'Missing required fields: type, message, severity',
      });
      return;
    }

    const alert = await Alert.create({
      type,
      message,
      severity,
      link,
      userId: userId || req.user?._id,
      isRead: false,
    });

    res.status(201).json({
      success: true,
      data: alert,
    });
  } catch (error: any) {
    res.status(400).json({
      success: false,
      message: error.message || 'Failed to create alert',
    });
  }
};

export const updateAlert = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { id } = req.params;
    const { isRead } = req.body;

    const alert = await Alert.findByIdAndUpdate(
      id,
      { isRead: isRead !== undefined ? isRead : true },
      { new: true }
    );

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

    res.json({
      success: true,
      data: alert,
    });
  } catch (error: any) {
    res.status(400).json({
      success: false,
      message: error.message || 'Failed to update alert',
    });
  }
};

export const deleteAlert = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { id } = req.params;

    const alert = await Alert.findByIdAndDelete(id);

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

    res.json({
      success: true,
      message: 'Alert deleted successfully',
    });
  } catch (error: any) {
    res.status(400).json({
      success: false,
      message: error.message || 'Failed to delete alert',
    });
  }
};

/**
 * Sync VCOM alarms for a project
 */
export const syncVCOMAlarms = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { projectId } = req.params;
    const { status, severity } = req.query;

    if (!projectId) {
      res.status(400).json({
        success: false,
        message: 'Project ID is required',
      });
      return;
    }

    const options: { status?: 'open' | 'closed'; severity?: 'normal' | 'high' | 'critical' } = {};
    if (status && (status === 'open' || status === 'closed')) {
      options.status = status;
    }
    if (severity && (severity === 'normal' || severity === 'high' || severity === 'critical')) {
      options.severity = severity;
    }

    // console.log(`[VCOM Alarm] Syncing alarms for project ${projectId}...`);
    const result = await syncVCOMAlarmsForProject(projectId, options);

    res.json({
      success: true,
      message: `Synced ${result.synced} alarms (${result.errors} errors)`,
      data: result,
    });
  } catch (error: any) {
    // console.error('[VCOM Alarm] Sync error:', error);
    let errorMessage = error.message || 'Failed to sync VCOM alarms';
    if (errorMessage.includes('OAuth failed') || errorMessage.includes('invalid_grant')) {
      errorMessage = 'Kết nối VCOM thất bại: Tài khoản, mật khẩu hoặc V2 API Key cấu hình trong Cài đặt hệ thống chưa chính xác.';
    }
    res.status(200).json({
      success: false,
      message: errorMessage,
    });
  }
};

/**
 * Get VCOM alarms live (from API, not MongoDB)
 */
export const getVCOMAlarmsLiveController = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { projectId } = req.query;
    const { status, severity } = req.query;

    if (!projectId || typeof projectId !== 'string') {
      res.status(400).json({
        success: false,
        message: 'Project ID is required',
      });
      return;
    }

    const options: { status?: 'open' | 'closed'; severity?: 'normal' | 'high' | 'critical' } = {};
    if (status && (status === 'open' || status === 'closed')) {
      options.status = status;
    }
    if (severity && (severity === 'normal' || severity === 'high' || severity === 'critical')) {
      options.severity = severity;
    }

    // console.log(`[VCOM Alarm] Fetching live alarms for project ${projectId}...`);
    const alarms = await getVCOMAlarmsLiveService(projectId, options);

    // Transform to Alert format for frontend compatibility
    const formattedAlarms = alarms.map((alarm: any) => {
      const severityMap: Record<string, 'Info' | 'Warning' | 'Critical'> = {
        'normal': 'Info',
        'high': 'Warning',
        'critical': 'Critical',
      };
      
      const alarmTypeMap: Record<string, string> = {
        'total-outage': 'Mất điện hoàn toàn',
        'data-outage': 'Mất dữ liệu',
        'communication-outage': 'Mất kết nối',
        'misproduction': 'Sản xuất thấp',
        'string-outage': 'Mất chuỗi',
        'sensor-outage': 'Lỗi cảm biến',
        'battery-charge-level': 'Mức pin bất thường',
        'custom': 'Cảnh báo tùy chỉnh',
      };

      const componentName = alarm.component?.name || alarm.component?.id || 'Thiết bị';
      const alarmTypeText = alarmTypeMap[alarm.alarmType] || alarm.alarmType || 'Cảnh báo';
      
      let message = `${alarmTypeText} - ${componentName}`;
      if (alarm.affectedPower && alarm.affectedPower > 0) {
        message += ` (Ảnh hưởng ${alarm.affectedPower.toFixed(1)}% công suất)`;
      }
      if (alarm.losses && alarm.losses > 0) {
        message += ` - Ước tính mất ${alarm.losses.toFixed(2)} kWh`;
      }

      return {
        _id: `vcom-${alarm.id}`,
        type: 'VCOMAlarm',
        message,
        severity: severityMap[alarm.severity] || 'Info',
        createdAt: new Date(alarm.createdAt),
        isRead: false,
        link: alarm.ticketId ? `/tickets/${alarm.ticketId}` : undefined,
        vcomAlarmId: alarm.id,
        systemKey: alarm.systemKey,
        alarmType: alarm.alarmType,
        componentId: alarm.component?.id,
        componentType: alarm.component?.type,
        componentName: alarm.component?.name,
        startedAt: alarm.startedAt ? new Date(alarm.startedAt) : undefined,
        duration: alarm.duration,
        affectedPower: alarm.affectedPower,
        losses: alarm.losses,
        ticketId: alarm.ticketId,
      };
    });

    res.json({
      success: true,
      data: formattedAlarms,
      source: 'live',
      message: `Fetched ${formattedAlarms.length} alarms from Meteocontrol V2 API`,
    });
  } catch (error: any) {
    // console.error('[VCOM Alarm] Get live alarms error:', error);
    let errorMessage = error.message || 'Failed to fetch VCOM alarms';
    if (errorMessage.includes('OAuth failed') || errorMessage.includes('invalid_grant')) {
      errorMessage = 'Kết nối VCOM thất bại: Tài khoản, mật khẩu hoặc V2 API Key cấu hình trong Cài đặt hệ thống chưa chính xác.';
    }
    res.status(200).json({
      success: false,
      message: errorMessage,
      data: [],
    });
  }
};
