const TherapistProfile = require("../../models/TherapistProfile");
const User = require("../../models/userModel");
const Appointment = require("../../models/Appointment");
const mongoose = require("mongoose");

// Get therapist profile
const getTherapistProfile = async (req, res) => {
  try {
    const userId = req.user.id;
    
    let profile = await TherapistProfile.findOne({ user: userId }).populate('user', 'fullname email mobile gender');
    
    // If no profile exists, create a basic one
    if (!profile) {
      const user = await User.findById(userId);
      if (!user || user.role !== 'doctor') {
        return res.status(403).json({
          success: false,
          message: "Access denied. Only therapists can access this resource."
        });
      }
      
      profile = new TherapistProfile({
        user: userId,
        fullName: user.fullname || '',
        professionalTitle: 'Therapist',
        yearsOfExperience: 0,
        therapyModes: ['Online'],
        therapyTypes: ['Individual Therapy']
      });
      
      await profile.save();
    }
    
    return res.status(200).json({
      success: true,
      message: "Therapist profile fetched successfully",
      data: profile
    });
    
  } catch (error) {
    console.error("Get therapist profile error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

// Update basic therapist information
const updateBasicInfo = async (req, res) => {
  try {
    const userId = req.user.id;
    const { 
      fullName, 
      professionalTitle, 
      yearsOfExperience, 
      specializations,
      languages,
      bio 
    } = req.body;
    
    // Validation
    if (!fullName || !professionalTitle || yearsOfExperience === undefined) {
      return res.status(400).json({
        success: false,
        message: "Full name, professional title, and years of experience are required"
      });
    }
    
    if (yearsOfExperience < 0 || yearsOfExperience > 50) {
      return res.status(400).json({
        success: false,
        message: "Years of experience must be between 0 and 50"
      });
    }
    
    let profile = await TherapistProfile.findOne({ user: userId });
    
    if (!profile) {
      return res.status(404).json({
        success: false,
        message: "Therapist profile not found"
      });
    }
    
    // Store changes for approval tracking
    const changes = {
      fullName: { old: profile.fullName, new: fullName },
      professionalTitle: { old: profile.professionalTitle, new: professionalTitle },
      yearsOfExperience: { old: profile.yearsOfExperience, new: yearsOfExperience }
    };
    
    // Update profile
    profile.fullName = fullName;
    profile.professionalTitle = professionalTitle;
    profile.yearsOfExperience = yearsOfExperience;
    
    if (specializations) profile.specializations = specializations;
    if (languages) profile.languages = languages;
    if (bio) profile.bio = bio;
    
    // Add to approval history
    profile.approvalHistory.push({
      status: 'changes_requested',
      reason: 'Basic information updated',
      changes: changes
    });
    
    await profile.save();
    
    return res.status(200).json({
      success: true,
      message: "Basic information updated successfully",
      data: profile
    });
    
  } catch (error) {
    console.error("Update basic info error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

// Update therapy delivery preferences
const updateTherapyPreferences = async (req, res) => {
  try {
    const userId = req.user.id;
    const { therapyModes, therapyTypes } = req.body;
    
    // Validation
    if (!therapyModes || !Array.isArray(therapyModes) || therapyModes.length === 0) {
      return res.status(400).json({
        success: false,
        message: "At least one therapy mode must be selected"
      });
    }
    
    if (!therapyTypes || !Array.isArray(therapyTypes) || therapyTypes.length === 0) {
      return res.status(400).json({
        success: false,
        message: "At least one therapy type must be selected"
      });
    }
    
    const validModes = ["Online", "Offline", "Hybrid"];
    const validTypes = ["Individual Therapy", "Couples Therapy", "Family Therapy", "Therapy for Children"];
    
    // Validate therapy modes
    const invalidModes = therapyModes.filter(mode => !validModes.includes(mode));
    if (invalidModes.length > 0) {
      return res.status(400).json({
        success: false,
        message: `Invalid therapy modes: ${invalidModes.join(', ')}`
      });
    }
    
    // Validate therapy types
    const invalidTypes = therapyTypes.filter(type => !validTypes.includes(type));
    if (invalidTypes.length > 0) {
      return res.status(400).json({
        success: false,
        message: `Invalid therapy types: ${invalidTypes.join(', ')}`
      });
    }
    
    let profile = await TherapistProfile.findOne({ user: userId });
    
    if (!profile) {
      return res.status(404).json({
        success: false,
        message: "Therapist profile not found"
      });
    }
    
    // Store changes for approval tracking
    const changes = {
      therapyModes: { old: profile.therapyModes, new: therapyModes },
      therapyTypes: { old: profile.therapyTypes, new: therapyTypes }
    };
    
    // Update preferences
    profile.therapyModes = therapyModes;
    profile.therapyTypes = therapyTypes;
    
    // Trigger admin approval if significant changes
    profile.approvalStatus = 'pending';
    profile.approvalHistory.push({
      status: 'pending',
      reason: 'Therapy delivery preferences updated - requires admin approval',
      changes: changes
    });
    
    await profile.save();
    
    return res.status(200).json({
      success: true,
      message: "Therapy preferences updated successfully. Changes sent for admin approval.",
      data: profile,
      requiresApproval: true
    });
    
  } catch (error) {
    console.error("Update therapy preferences error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

// Update availability settings
const updateAvailability = async (req, res) => {
  try {
    const userId = req.user.id;
    const { 
      weeklyAvailability, 
      maxSessionsPerDay, 
      breakDurationMinutes,
      unavailableDates 
    } = req.body;
    
    let profile = await TherapistProfile.findOne({ user: userId });
    
    if (!profile) {
      return res.status(404).json({
        success: false,
        message: "Therapist profile not found"
      });
    }
    
    // Validation
    if (maxSessionsPerDay && (maxSessionsPerDay < 1 || maxSessionsPerDay > 12)) {
      return res.status(400).json({
        success: false,
        message: "Max sessions per day must be between 1 and 12"
      });
    }
    
    if (breakDurationMinutes && (breakDurationMinutes < 15 || breakDurationMinutes > 120)) {
      return res.status(400).json({
        success: false,
        message: "Break duration must be between 15 and 120 minutes"
      });
    }
    
    // Validate time slots format
    if (weeklyAvailability) {
      const days = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
      const timeRegex = /^([01]\d|2[0-3]):([0-5]\d)$/;
      
      for (const day of days) {
        if (weeklyAvailability[day] && weeklyAvailability[day].slots) {
          for (const slot of weeklyAvailability[day].slots) {
            if (!timeRegex.test(slot.startTime) || !timeRegex.test(slot.endTime)) {
              return res.status(400).json({
                success: false,
                message: `Invalid time format in ${day} slots. Use HH:MM format.`
              });
            }
            
            // Validate that end time is after start time
            if (slot.startTime >= slot.endTime) {
              return res.status(400).json({
                success: false,
                message: `End time must be after start time in ${day} slots.`
              });
            }
          }
        }
      }
    }
    
    // Store changes for approval tracking
    const changes = {};
    if (weeklyAvailability) changes.weeklyAvailability = { old: profile.weeklyAvailability, new: weeklyAvailability };
    if (maxSessionsPerDay) changes.maxSessionsPerDay = { old: profile.maxSessionsPerDay, new: maxSessionsPerDay };
    if (breakDurationMinutes) changes.breakDurationMinutes = { old: profile.breakDurationMinutes, new: breakDurationMinutes };
    
    // Update availability
    if (weeklyAvailability) profile.weeklyAvailability = weeklyAvailability;
    if (maxSessionsPerDay) profile.maxSessionsPerDay = maxSessionsPerDay;
    if (breakDurationMinutes) profile.breakDurationMinutes = breakDurationMinutes;
    if (unavailableDates) profile.unavailableDates = unavailableDates;
    
    // Trigger admin approval for availability changes
    profile.approvalStatus = 'pending';
    profile.approvalHistory.push({
      status: 'pending',
      reason: 'Availability settings updated - requires admin approval',
      changes: changes
    });
    
    await profile.save();
    
    return res.status(200).json({
      success: true,
      message: "Availability settings updated successfully. Changes sent for admin approval.",
      data: profile,
      requiresApproval: true
    });
    
  } catch (error) {
    console.error("Update availability error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

// Update notification preferences
const updateNotificationPreferences = async (req, res) => {
  try {
    const userId = req.user.id;
    const { notificationPreferences } = req.body;
    
    if (!notificationPreferences || typeof notificationPreferences !== 'object') {
      return res.status(400).json({
        success: false,
        message: "Valid notification preferences object is required"
      });
    }
    
    let profile = await TherapistProfile.findOne({ user: userId });
    
    if (!profile) {
      return res.status(404).json({
        success: false,
        message: "Therapist profile not found"
      });
    }
    
    // Update notification preferences (no admin approval needed)
    profile.notificationPreferences = {
      ...profile.notificationPreferences,
      ...notificationPreferences
    };
    
    await profile.save();
    
    return res.status(200).json({
      success: true,
      message: "Notification preferences updated successfully",
      data: profile
    });
    
  } catch (error) {
    console.error("Update notification preferences error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

// Update account settings
const updateAccountSettings = async (req, res) => {
  try {
    const userId = req.user.id;
    const { displayLanguage, isActive } = req.body;
    
    let profile = await TherapistProfile.findOne({ user: userId });
    
    if (!profile) {
      return res.status(404).json({
        success: false,
        message: "Therapist profile not found"
      });
    }
    
    // Update account settings
    if (displayLanguage) {
      const validLanguages = ["English", "Hindi", "Both"];
      if (!validLanguages.includes(displayLanguage)) {
        return res.status(400).json({
          success: false,
          message: "Invalid display language"
        });
      }
      profile.displayLanguage = displayLanguage;
    }
    
    if (isActive !== undefined) {
      profile.isActive = isActive;
    }
    
    await profile.save();
    
    return res.status(200).json({
      success: true,
      message: "Account settings updated successfully",
      data: profile
    });
    
  } catch (error) {
    console.error("Update account settings error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

// Add/Update certifications
const updateCertifications = async (req, res) => {
  try {
    const userId = req.user.id;
    const { certifications } = req.body;
    
    if (!Array.isArray(certifications)) {
      return res.status(400).json({
        success: false,
        message: "Certifications must be an array"
      });
    }
    
    let profile = await TherapistProfile.findOne({ user: userId });
    
    if (!profile) {
      return res.status(404).json({
        success: false,
        message: "Therapist profile not found"
      });
    }
    
    // Validate certification data
    for (const cert of certifications) {
      if (!cert.name || !cert.issuingBody) {
        return res.status(400).json({
          success: false,
          message: "Each certification must have a name and issuing body"
        });
      }
    }
    
    profile.certifications = certifications;
    await profile.save();
    
    return res.status(200).json({
      success: true,
      message: "Certifications updated successfully",
      data: profile
    });
    
  } catch (error) {
    console.error("Update certifications error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

// Get therapist availability for a specific date
const getAvailabilityForDate = async (req, res) => {
  try {
    const userId = req.user.id;
    const { date } = req.query;
    
    if (!date) {
      return res.status(400).json({
        success: false,
        message: "Date is required"
      });
    }
    
    const requestedDate = new Date(date);
    if (isNaN(requestedDate.getTime())) {
      return res.status(400).json({
        success: false,
        message: "Invalid date format"
      });
    }
    
    const profile = await TherapistProfile.findOne({ user: userId });
    
    if (!profile) {
      return res.status(404).json({
        success: false,
        message: "Therapist profile not found"
      });
    }
    
    // Check if date is in unavailable dates
    const isUnavailable = profile.unavailableDates.some(unavailableDate => {
      const unavailableDateObj = new Date(unavailableDate.date);
      return unavailableDateObj.toDateString() === requestedDate.toDateString();
    });
    
    if (isUnavailable) {
      return res.status(200).json({
        success: true,
        message: "Therapist is not available on this date",
        data: {
          available: false,
          slots: [],
          reason: "Marked as unavailable"
        }
      });
    }
    
    // Get available slots for the date
    const availableSlots = profile.getAvailableSlotsForDate(requestedDate);
    
    // Get existing appointments for this date to exclude booked slots
    const existingAppointments = await Appointment.find({
      doctor: userId,
      date: {
        $gte: new Date(requestedDate.setHours(0, 0, 0, 0)),
        $lte: new Date(requestedDate.setHours(23, 59, 59, 999))
      },
      status: { $in: ['scheduled', 'completed'] }
    });
    
    // Filter out booked slots
    const bookedSlots = existingAppointments.map(apt => ({
      startTime: apt.timeSlot.startTime,
      endTime: apt.timeSlot.endTime
    }));
    
    const freeSlots = availableSlots.filter(slot => {
      return !bookedSlots.some(booked => 
        (slot.startTime >= booked.startTime && slot.startTime < booked.endTime) ||
        (slot.endTime > booked.startTime && slot.endTime <= booked.endTime)
      );
    });
    
    return res.status(200).json({
      success: true,
      message: "Availability fetched successfully",
      data: {
        available: freeSlots.length > 0,
        slots: freeSlots,
        totalSessions: existingAppointments.length,
        maxSessions: profile.maxSessionsPerDay
      }
    });
    
  } catch (error) {
    console.error("Get availability error:", error);
    return res.status(500).json({
      success: false,
      message: "Server Error",
      error: error.message
    });
  }
};

module.exports = {
  getTherapistProfile,
  updateBasicInfo,
  updateTherapyPreferences,
  updateAvailability,
  updateNotificationPreferences,
  updateAccountSettings,
  updateCertifications,
  getAvailabilityForDate
};
