import { Response } from 'express';
import { KPI } from '../models/KPI';
import { Ticket } from '../models/Ticket';
import { FinancialData } from '../models/Financial';
import { Alert } from '../models/Alert';
import { AuthRequest } from '../middleware/auth.middleware';
import mongoose from 'mongoose';
import { findProjectByIdOrCode } from '../utils/projectHelper';

export const getKPIs = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { siteId } = req.query;

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

    // Handle both ObjectId and string ID (demo data)
    let projectId: any = siteId;
    if (mongoose.Types.ObjectId.isValid(siteId as string)) {
      projectId = new mongoose.Types.ObjectId(siteId as string);
    } else {
      // Use helper function to find project without Mongoose casting errors
      const project = await findProjectByIdOrCode(siteId as string);
      if (!project) {
        res.status(404).json({
          success: false,
          message: `Project with ID or code "${siteId}" not found`,
        });
        return;
      }
      projectId = project._id;
    }

    // Use native MongoDB query if projectId is a string to avoid ObjectId casting
    let kpis;
    if (typeof projectId === 'string' && !mongoose.Types.ObjectId.isValid(projectId)) {
      const db = mongoose.connection.db;
      if (!db) throw new Error('Database connection not established');
      const kpisCollection = db.collection('kpis');
      kpis = await kpisCollection.find({ siteId: projectId })
        .sort({ date: -1 })
        .limit(12)
        .toArray();
    } else {
      kpis = await KPI.find({ siteId: projectId })
        .sort({ date: -1 })
        .limit(12)
        .lean();
    }

    res.json({
      success: true,
      data: kpis.reverse(), // Reverse to get chronological order
    });
  } catch (error: any) {
    res.status(500).json({
      success: false,
      message: error.message || 'Failed to fetch KPIs',
    });
  }
};

export const getTickets = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { projectId } = req.query;
    const filter: any = {};

    if (projectId) {
      filter.projectId = projectId;
    }

    const tickets = await Ticket.find(filter)
      .populate('assetId', 'name code')
      .sort({ createdAt: -1 })
      .lean();

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

export const getFinancialData = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const { projectId: projectIdParam } = req.query;

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

    // Handle both ObjectId and string ID (demo data)
    let projectId: any = projectIdParam;
    if (mongoose.Types.ObjectId.isValid(projectIdParam as string)) {
      projectId = new mongoose.Types.ObjectId(projectIdParam as string);
    } else {
      // Use helper function to find project without Mongoose casting errors
      const project = await findProjectByIdOrCode(projectIdParam as string);
      if (!project) {
        res.status(404).json({
          success: false,
          message: `Project with ID or code "${projectIdParam}" not found`,
        });
        return;
      }
      projectId = project._id;
    }

    // Use native MongoDB query if projectId is a string to avoid ObjectId casting
    let financials;
    if (typeof projectId === 'string' && !mongoose.Types.ObjectId.isValid(projectId)) {
      const db = mongoose.connection.db;
      if (!db) throw new Error('Database connection not established');
      const financialsCollection = db.collection('financials');
      financials = await financialsCollection.find({ projectId })
        .sort({ month: -1 })
        .toArray();
    } else {
      financials = await FinancialData.find({ projectId })
        .sort({ month: -1 })
        .lean();
    }

    // Calculate cost breakdown (mock data structure)
    const breakdown = [
      { name: 'Nhân sự O&M', value: 35 },
      { name: 'Vật tư thay thế', value: 20 },
      { name: 'Vệ sinh tấm pin', value: 15 },
      { name: 'Bảo hiểm', value: 10 },
      { name: 'Thuê đất', value: 10 },
      { name: 'Khác', value: 10 },
    ];

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

export const getAlerts = async (req: AuthRequest, res: Response): Promise<void> => {
  try {
    const alerts = await Alert.find({
      $or: [
        { userId: req.user?._id },
        { userId: { $exists: false } }, // Global alerts
      ],
    })
      .sort({ createdAt: -1 })
      .limit(50)
      .lean();

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