const User = require("../../models/userModel");
const Appointment = require("../../models/Appointment");
const AppointmentFeedback = require("../../models/AppointmentFeedback");
const Plans = require("../../models/Plan");
const Therapy = require("../../models/Therapy");
const moment = require("moment");
const mongoose = require("mongoose");

/**
 * Get complete dashboard data for therapist
 * Includes all sections: Quick Glance, Impact Tracker, Client Flow, Stay on Track, etc.
 */
exports.getDashboardData = async (req, res) => {
  try {
    const doctorId = req.user?.id;
    const { period = 'month' } = req.query; // month, quarter, year
    
    if (!doctorId) {
      return res.status(401).json({
        success: false,
        message: "Doctor ID not found in request"
      });
    }

    // Get date ranges based on period
    const { startDate, endDate } = getDateRange(period);
    const todayStart = moment().startOf('day').toDate();
    const todayEnd = moment().endOf('day').toDate();

    // Execute all dashboard queries in parallel for better performance
    const [
      quickGlanceData,
      impactTrackerData,
      clientFlowData,
      stayOnTrackData,
      upcomingSessionsData,
      feedbackOverviewData
    ] = await Promise.all([
      getQuickGlanceData(doctorId, todayStart, todayEnd),
      getImpactTrackerData(doctorId, startDate, endDate, period),
      getClientFlowData(doctorId, startDate, endDate),
      getStayOnTrackData(doctorId),
      getUpcomingSessionsData(doctorId),
      getFeedbackOverviewData(doctorId)
    ]);

    const dashboardData = {
      quickGlance: quickGlanceData,
      impactTracker: impactTrackerData,
      clientFlow: clientFlowData,
      stayOnTrack: stayOnTrackData,
      upcomingSessions: upcomingSessionsData,
      feedbackOverview: feedbackOverviewData,
      period: period
    };

    return res.status(200).json({
      success: true,
      message: "Dashboard data fetched successfully",
      data: dashboardData
    });

  } catch (error) {
    console.error("Dashboard data fetch error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

/**
 * Get Quick Glance KPIs for today
 */
const getQuickGlanceData = async (doctorId, todayStart, todayEnd) => {
  try {
    // Today's sessions count
    const todaysSessions = await Appointment.countDocuments({
      doctor: doctorId,
      date: { $gte: todayStart, $lte: todayEnd },
      status: { $nin: ['pending', 'cancelled'] }
    });

    // Completed sessions today
    const completedToday = await Appointment.countDocuments({
      doctor: doctorId,
      date: { $gte: todayStart, $lte: todayEnd },
      status: 'completed'
    });

    // Cancelled/No-shows today
    const cancelledToday = await Appointment.countDocuments({
      doctor: doctorId,
      date: { $gte: todayStart, $lte: todayEnd },
      status: 'cancelled'
    });

    // Plan progress calculation
    const activePlans = await Plans.find({
      doctorId: doctorId,
      status: 'active'
    });

    let totalProgress = 0;
    let planCount = 0;
    
    activePlans.forEach(plan => {
      if (plan.sessionCount > 0) {
        const progress = (plan.completedSessions / plan.sessionCount) * 100;
        totalProgress += progress;
        planCount++;
      }
    });

    const avgPlanProgress = planCount > 0 ? Math.round(totalProgress / planCount) : 0;

    // Next session today
    const nextSession = await Appointment.findOne({
      doctor: doctorId,
      date: { $gte: new Date(), $lte: todayEnd },
      status: 'scheduled'
    })
    .populate('patient', 'fullname')
    .sort({ date: 1, 'timeSlot.startTime': 1 })
    .limit(1);

    return {
      todaysSessions,
      completedToday,
      cancelledNoShows: cancelledToday,
      planProgress: avgPlanProgress,
      nextSession: nextSession ? {
        clientId: nextSession.patient?._id,
        clientName: nextSession.patient?.fullname,
        time: nextSession.timeSlot?.startTime,
        appointmentId: nextSession._id
      } : null
    };
  } catch (error) {
    console.error("Quick Glance data error:", error);
    throw error;
  }
};

/**
 * Get Impact Tracker metrics
 */
const getImpactTrackerData = async (doctorId, startDate, endDate, period) => {
  try {
    // Consultations this period
    const consultationsThisPeriod = await Appointment.countDocuments({
      doctor: doctorId,
      createdAt: { $gte: startDate, $lte: endDate },
      status: { $ne: 'pending' }
    });

    // Plans suggested this period
    const plansSuggested = await Plans.countDocuments({
      doctorId: doctorId,
      createdAt: { $gte: startDate, $lte: endDate }
    });

    // Plans accepted this period
    const plansAccepted = await Plans.countDocuments({
      doctorId: doctorId,
      createdAt: { $gte: startDate, $lte: endDate },
      status: { $in: ['active', 'completed'] }
    });

    const acceptanceRate = plansSuggested > 0 ? Math.round((plansAccepted / plansSuggested) * 100) : 0;

    // Get trend data for graph
    const trendData = await getTrendData(doctorId, period);

    return {
      consultationsThisPeriod,
      plansSuggested,
      plansAccepted,
      acceptanceRate,
      trendData
    };
  } catch (error) {
    console.error("Impact Tracker data error:", error);
    throw error;
  }
};

/**
 * Get Client Flow Insights
 */
const getClientFlowData = async (doctorId, startDate, endDate) => {
  try {
    // Average sessions per client calculation
    const clientSessions = await Appointment.aggregate([
      {
        $match: {
          doctor: new mongoose.Types.ObjectId(doctorId),
          status: 'completed',
          createdAt: { $gte: startDate, $lte: endDate }
        }
      },
      {
        $group: {
          _id: '$patient',
          sessionCount: { $sum: 1 }
        }
      },
      {
        $group: {
          _id: null,
          avgSessions: { $avg: '$sessionCount' },
          totalClients: { $sum: 1 }
        }
      }
    ]);

    const avgSessionsPerClient = clientSessions.length > 0 ? 
      parseFloat(clientSessions[0].avgSessions.toFixed(1)) : 0;

    // Session outcome breakdown
    const sessionOutcomes = await Appointment.aggregate([
      {
        $match: {
          doctor: new mongoose.Types.ObjectId(doctorId),
          createdAt: { $gte: startDate, $lte: endDate },
          status: { $ne: 'pending' }
        }
      },
      {
        $group: {
          _id: '$status',
          count: { $sum: 1 }
        }
      }
    ]);

    const outcomeBreakdown = {
      completed: 0,
      cancelled: 0,
      noShows: 0
    };

    sessionOutcomes.forEach(outcome => {
      if (outcome._id === 'completed') outcomeBreakdown.completed = outcome.count;
      if (outcome._id === 'cancelled') outcomeBreakdown.cancelled = outcome.count;
      // Note: You might want to add a 'no-show' status to differentiate from cancelled
    });

    // Top 3 client concerns from therapy forms
    const topConcerns = await getTopClientConcerns(doctorId);

    return {
      avgSessionsPerClient,
      sessionOutcomes: outcomeBreakdown,
      topConcerns
    };
  } catch (error) {
    console.error("Client Flow data error:", error);
    throw error;
  }
};

/**
 * Get Stay on Track alerts and pending tasks
 */
const getStayOnTrackData = async (doctorId) => {
  try {
    // Notes pending - completed sessions without notes
    const notesPending = await Appointment.countDocuments({
      doctor: doctorId,
      status: 'completed',
      $or: [{ notes: null }, { notes: '' }]
    });

    // Plans pending - users who had consultations but no plans created
    const plansPendingQuery = await Appointment.aggregate([
      {
        $match: {
          doctor: new mongoose.Types.ObjectId(doctorId),
          status: 'completed'
        }
      },
      {
        $lookup: {
          from: 'plans',
          localField: 'patient',
          foreignField: 'userId',
          as: 'plans'
        }
      },
      {
        $match: {
          plans: { $size: 0 }
        }
      },
      {
        $group: {
          _id: '$patient'
        }
      },
      {
        $count: 'count'
      }
    ]);

    const plansPending = plansPendingQuery.length > 0 ? plansPendingQuery[0].count : 0;

    // Client actions - recent plan acceptances and feedback
    const recentPlanAcceptances = await Plans.find({
      doctorId: doctorId,
      status: 'active',
      updatedAt: { $gte: moment().subtract(7, 'days').toDate() }
    })
    .populate('userId', 'fullname')
    .sort({ updatedAt: -1 })
    .limit(5);

    const recentFeedback = await AppointmentFeedback.find({
      doctor: doctorId,
      createdAt: { $gte: moment().subtract(7, 'days').toDate() }
    })
    .populate('patient', 'fullname')
    .populate('appointment')
    .sort({ createdAt: -1 })
    .limit(5);

    // Tomorrow's sessions
    const tomorrowStart = moment().add(1, 'day').startOf('day').toDate();
    const tomorrowEnd = moment().add(1, 'day').endOf('day').toDate();
    
    const tomorrowSessions = await Appointment.find({
      doctor: doctorId,
      date: { $gte: tomorrowStart, $lte: tomorrowEnd },
      status: 'scheduled'
    })
    .populate('patient', 'fullname')
    .sort({ 'timeSlot.startTime': 1 });

    // Admin alerts - feedback under 3 stars
    const lowRatingFeedback = await AppointmentFeedback.find({
      doctor: doctorId,
      rating: { $lt: 3 },
      createdAt: { $gte: moment().subtract(30, 'days').toDate() }
    })
    .populate('patient', 'fullname')
    .sort({ createdAt: -1 });

    return {
      notesPending,
      plansPending,
      clientActions: {
        planAcceptances: recentPlanAcceptances.map(plan => ({
          clientName: plan.userId?.fullname,
          acceptedAt: plan.updatedAt,
          planId: plan._id
        })),
        recentFeedback: recentFeedback.map(feedback => ({
          clientName: feedback.patient?.fullname,
          rating: feedback.rating,
          createdAt: feedback.createdAt,
          appointmentId: feedback.appointment
        }))
      },
      tomorrowSessions: tomorrowSessions.map(session => ({
        clientId: session.patient._id,
        clientName: session.patient.fullname,
        time: session.timeSlot.startTime,
        appointmentId: session._id
      })),
      adminAlerts: lowRatingFeedback.map(feedback => ({
        clientName: feedback.patient?.fullname,
        rating: feedback.rating,
        createdAt: feedback.createdAt
      }))
    };
  } catch (error) {
    console.error("Stay on Track data error:", error);
    throw error;
  }
};

/**
 * Get upcoming sessions data
 */
const getUpcomingSessionsData = async (doctorId) => {
  try {
    const upcomingSessions = await Appointment.find({
      doctor: doctorId,
      date: { $gt: new Date() },
      status: 'scheduled'
    })
    .populate('patient', 'fullname')
    .sort({ date: 1, 'timeSlot.startTime': 1 })
    .limit(5);

    return upcomingSessions.map(session => ({
      clientId: session.patient._id,
      clientName: session.patient.fullname,
      date: session.date,
      time: session.timeSlot.startTime,
      appointmentId: session._id
    }));
  } catch (error) {
    console.error("Upcoming sessions data error:", error);
    throw error;
  }
};

/**
 * Get feedback overview data
 */
const getFeedbackOverviewData = async (doctorId) => {
  try {
    // Average rating from last 10 sessions
    const recentFeedback = await AppointmentFeedback.find({
      doctor: doctorId
    })
    .sort({ createdAt: -1 })
    .limit(10);

    const avgRating = recentFeedback.length > 0 ? 
      (recentFeedback.reduce((sum, feedback) => sum + feedback.rating, 0) / recentFeedback.length).toFixed(1) : 0;

    // Recent feedback highlights
    const feedbackHighlights = await AppointmentFeedback.find({
      doctor: doctorId,
      review: { $ne: null, $ne: '' }
    })
    .sort({ createdAt: -1 })
    .limit(3);

    return {
      averageRating: parseFloat(avgRating),
      totalReviews: recentFeedback.length,
      highlights: feedbackHighlights.map(feedback => ({
        review: feedback.review,
        rating: feedback.rating,
        createdAt: feedback.createdAt
      }))
    };
  } catch (error) {
    console.error("Feedback overview data error:", error);
    throw error;
  }
};

/**
 * Get top client concerns from therapy intake forms
 */
const getTopClientConcerns = async (doctorId) => {
  try {
    // Get all patients of this doctor
    const doctorAppointments = await Appointment.find({
      doctor: doctorId,
      status: { $ne: 'pending' }
    }).distinct('patient');

    // Get therapy forms for these patients
    const therapyForms = await Therapy.find({
      user: { $in: doctorAppointments }
    });

    // Extract and count concerns
    const concernCounts = {};
    
    therapyForms.forEach(therapy => {
      // From individual concerns
      if (therapy.step3?.individualConcerns) {
        therapy.step3.individualConcerns.forEach(concern => {
          concernCounts[concern] = (concernCounts[concern] || 0) + 1;
        });
      }
      
      // From couple concerns
      if (therapy.step3?.coupleConcerns) {
        therapy.step3.coupleConcerns.forEach(concern => {
          concernCounts[concern] = (concernCounts[concern] || 0) + 1;
        });
      }
      
      // From family concerns
      if (therapy.step3?.familyConcerns) {
        therapy.step3.familyConcerns.forEach(concern => {
          concernCounts[concern] = (concernCounts[concern] || 0) + 1;
        });
      }

      // From general concern field
      if (therapy.concern) {
        concernCounts[therapy.concern] = (concernCounts[therapy.concern] || 0) + 1;
      }
    });

    // Sort and get top 3
    const sortedConcerns = Object.entries(concernCounts)
      .sort(([,a], [,b]) => b - a)
      .slice(0, 3)
      .map(([concern, count]) => ({ concern, count }));

    return sortedConcerns;
  } catch (error) {
    console.error("Top concerns data error:", error);
    return [];
  }
};

/**
 * Get trend data for charts
 */
const getTrendData = async (doctorId, period) => {
  try {
    let groupBy, dateFormat;
    let intervals;

    switch (period) {
      case 'quarter':
        groupBy = { $month: '$createdAt' };
        intervals = 3;
        dateFormat = 'MMM';
        break;
      case 'year':
        groupBy = { $month: '$createdAt' };
        intervals = 12;
        dateFormat = 'MMM';
        break;
      default: // month
        groupBy = { $dayOfMonth: '$createdAt' };
        intervals = 30;
        dateFormat = 'DD';
    }

    const trendData = await Appointment.aggregate([
      {
        $match: {
          doctor: new mongoose.Types.ObjectId(doctorId),
          status: { $ne: 'pending' },
          createdAt: { $gte: getDateRange(period).startDate }
        }
      },
      {
        $group: {
          _id: groupBy,
          consultations: { $sum: 1 },
          completed: {
            $sum: { $cond: [{ $eq: ['$status', 'completed'] }, 1, 0] }
          }
        }
      },
      { $sort: { '_id': 1 } }
    ]);

    return trendData;
  } catch (error) {
    console.error("Trend data error:", error);
    return [];
  }
};

/**
 * Helper function to get date ranges
 */
const getDateRange = (period) => {
  const now = moment();
  let startDate, endDate;

  switch (period) {
    case 'quarter':
      startDate = now.clone().subtract(3, 'months').startOf('month').toDate();
      endDate = now.clone().endOf('month').toDate();
      break;
    case 'year':
      startDate = now.clone().subtract(1, 'year').startOf('month').toDate();
      endDate = now.clone().endOf('month').toDate();
      break;
    default: // month
      startDate = now.clone().startOf('month').toDate();
      endDate = now.clone().endOf('month').toDate();
  }

  return { startDate, endDate };
};

/**
 * Get specific section data (for individual API calls)
 */
exports.getQuickGlance = async (req, res) => {
  try {
    const doctorId = req.user?.id;
    const todayStart = moment().startOf('day').toDate();
    const todayEnd = moment().endOf('day').toDate();

    const data = await getQuickGlanceData(doctorId, todayStart, todayEnd);

    return res.status(200).json({
      success: true,
      message: "Quick glance data fetched successfully",
      data
    });
  } catch (error) {
    console.error("Quick glance error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error"
    });
  }
};

exports.getImpactTracker = async (req, res) => {
  try {
    const doctorId = req.user?.id;
    const { period = 'month' } = req.query;
    const { startDate, endDate } = getDateRange(period);

    const data = await getImpactTrackerData(doctorId, startDate, endDate, period);

    return res.status(200).json({
      success: true,
      message: "Impact tracker data fetched successfully",
      data
    });
  } catch (error) {
    console.error("Impact tracker error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error"
    });
  }
};

exports.getClientFlow = async (req, res) => {
  try {
    const doctorId = req.user?.id;
    const { period = 'month' } = req.query;
    const { startDate, endDate } = getDateRange(period);

    const data = await getClientFlowData(doctorId, startDate, endDate);

    return res.status(200).json({
      success: true,
      message: "Client flow data fetched successfully",
      data
    });
  } catch (error) {
    console.error("Client flow error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error"
    });
  }
};

exports.getStayOnTrack = async (req, res) => {
  try {
    const doctorId = req.user?.id;
    const data = await getStayOnTrackData(doctorId);

    return res.status(200).json({
      success: true,
      message: "Stay on track data fetched successfully",
      data
    });
  } catch (error) {
    console.error("Stay on track error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error"
    });
  }
};


