import express from "express";
import { User } from "../models/user.js";
import SettingProfile from "../models/settingProfile.js";
import { authenticate } from "../middleware/authMiddleware.js";
import SubmitAiWebsite from "../models/submitAiWebsite.js";
import SubmitDirectory from "../models/submitDirectory.js";
import WebsiteSubmission from "../models/websiteSubmission.js";
import Award from "../models/award.js";
import { uploadToDropbox, generateUniqueFilename, getFileExtensionFromBase64 } from "../utils/dropboxService.js";
const router = express.Router();

// 🔒 Middleware to prevent caching of profile responses
const noCacheMiddleware = (req, res, next) => {
  res.set({
    'Cache-Control': 'no-store, no-cache, must-revalidate, private, max-age=0',
    'Pragma': 'no-cache',
    'Expires': '0',
    'Vary': 'Authorization' // Important: tells proxies to vary by Authorization header
  });
  next();
};

// Apply no-cache to all profile routes
router.use(noCacheMiddleware);

// Utility function to clean social media URLs
const cleanSocial = v => (typeof v === "string" && v.trim() !== "" ? v.trim() : undefined);

// GET user's profile - Check if profile exists and return it
router.get("/", authenticate, async (req, res) => {
  try {
    const userId = req.user.id;

    // ✅ Find profile by submittedBy (user ID)
    const existingProfile = await SettingProfile.findOne({ submittedBy: userId });

    if (!existingProfile) {
      return res.status(404).json({
        message: "Profile not found",
        exists: false,
      });
    }

    console.log("Existing profile found for user:", userId);

    // ✅ Fetch all websites submitted by this user
    const userWebsites = await WebsiteSubmission.find({ submittedBy: userId }).select("_id");
    const websiteIds = userWebsites.map((site) => site._id);

    // ✅ Count awards for each category
    const [sotdCount, sotwCount, sotmCount, sotyCount] = await Promise.all([
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTD" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTW" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTM" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTY" }),
    ]);

    // ✅ Combine everything in response
    return res.status(200).json({
      message: "Profile found",
      exists: true,
      profile: existingProfile,
      awardStats: {
        sotdCount,
        sotwCount,
        sotmCount,
        sotyCount,
      },
    });
  } catch (err) {
    console.error("Error fetching profile and awards:", err);
    return res.status(500).json({
      message: "Error occurred during profile fetching",
      error: err.message,
    });
  }
});

// GET username only (your existing endpoint)
router.get("/user", authenticate, async (req, res) => {
  try {
    const id = req.user.id;
    const user = await User.findById(id).select("userName").exec();

    if (!user) {
      return res.status(404).json({ message: "User not found" });
    }

    console.log("Fetched username is", user.userName);
    return res.status(200).json({ 
      message: "User found", 
      userName: user.userName 
    });
  } catch (err) {
    console.error("Error fetching user info:", err);
    return res.status(500).json({ 
      message: "Error occurred during user fetching" 
    });
  }
});

// GET public user profile by username (NO authentication required)
router.get("/user/:username", async (req, res) => {
  try {
    const { username } = req.params;
    console.log("Fetching public profile for username:", username);

    // Find user by username
    const user = await User.findOne({ userName: username }).select("_id userName");
    
    if (!user) {
      return res.status(404).json({
        message: "User not found",
        exists: false,
      });
    }

    // Find profile by user ID
    const profile = await SettingProfile.findOne({ submittedBy: user._id });

    if (!profile) {
      return res.status(404).json({
        message: "Profile not found",
        exists: false,
      });
    }

    // Fetch all submissions by this user
    const [websites, directories, aiWebsites] = await Promise.all([
      WebsiteSubmission.find({ submittedBy: user._id })
        .select("Title Img Description Category Tags Colors Submitted_URL createdAt")
        .sort({ createdAt: -1 })
        .lean(),
      SubmitDirectory.find({ submittedBy: user._id })
        .select("title websiteUrl screenshot description category tags createdAt")
        .sort({ createdAt: -1 })
        .lean(),
      SubmitAiWebsite.find({ submittedBy: user._id })
        .select("title websiteUrl screenshot description category tags createdAt")
        .sort({ createdAt: -1 })
        .lean(),
    ]);

    // Get website IDs for award counting
    const websiteIds = websites.map((site) => site._id);

    // Count awards for each category
    const [sotdCount, sotwCount, sotmCount, sotyCount] = await Promise.all([
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTD" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTW" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTM" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTY" }),
    ]);

    // Format submissions with type indicator
    const formattedWebsites = websites.map(w => ({ ...w, type: 'website' }));
    const formattedDirectories = directories.map(d => ({ 
      ...d, 
      type: 'directory',
      Title: d.title,
      Img: d.screenshot,
      Description: d.description,
      Category: d.category,
      Tags: d.tags,
      Submitted_URL: d.websiteUrl
    }));
    const formattedAIWebsites = aiWebsites.map(a => ({ 
      ...a, 
      type: 'ai-website',
      Title: a.title,
      Img: a.screenshot,
      Description: a.description,
      Category: a.category,
      Tags: a.tags,
      Submitted_URL: a.websiteUrl
    }));

    const allSubmissions = [
      ...formattedWebsites,
      ...formattedDirectories,
      ...formattedAIWebsites
    ].sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));

    // Return public profile data
    return res.status(200).json({
      message: "Public profile found",
      exists: true,
      profile: {
        username: profile.username,
        displayName: profile.displayName,
        profilePhoto: profile.profilePhoto,
        country: profile.country,
        profile: profile.profile,
        url: profile.url,
        facebook: profile.facebook,
        instagram: profile.instagram,
        twitter: profile.twitter,
        linkedin: profile.linkedin,
        youtube: profile.youtube,
        tiktok: profile.tiktok,
        createdAt: profile.createdAt,
        awardStats: {
          sotdCount,
          sotwCount,
          sotmCount,
          sotyCount,
        }
      },
      submissions: allSubmissions,
      stats: {
        totalWebsites: websites.length,
        totalDirectories: directories.length,
        totalAIWebsites: aiWebsites.length,
        totalSubmissions: allSubmissions.length,
        totalAwards: sotdCount + sotwCount + sotmCount + sotyCount
      }
    });
  } catch (err) {
    console.error("Error fetching public profile:", err);
    return res.status(500).json({
      message: "Error occurred during profile fetching",
      error: err.message,
    });
  }
});

// POST/PUT - Create or Update profile
router.post("/", authenticate, async (req, res) => {
  try {
    console.log("Incoming Data:", req.body);

    const userId = req.user.id;
    const {
      Username,
      DisplayName,  
      URL,
      Profile,
      Country,
      ProfilePhoto,
      Facebook,
      Instagram,
      Twitter,
      Linkedin,
      Tiktok,
      Youtube,
    } = req.body;

    // Validate username doesn't contain spaces
    if (Username && /\s/.test(Username)) {
      return res.status(400).json({ 
        message: "Username cannot contain spaces" 
      });
    }

    // Check if profile already exists for this user
    const existingProfile = await SettingProfile.findOne({ submittedBy: userId });

    // ✅ Upload profile photo to Dropbox if provided
    let profilePhotoUrl = ProfilePhoto;
    if (ProfilePhoto && ProfilePhoto.startsWith('data:image')) {
      const extension = getFileExtensionFromBase64(ProfilePhoto);
      const filename = generateUniqueFilename(`${Username}-profile.${extension}`, 'profile');
      profilePhotoUrl = await uploadToDropbox(ProfilePhoto, filename, '/profile-photos');
      console.log('✅ Profile photo uploaded to Dropbox:', profilePhotoUrl);
    }

    const profileData = {
      username: Username,
      displayName: DisplayName,
      url: URL,
      profile: Profile,
      country: Country,
      profilePhoto: profilePhotoUrl, // ✅ Use Dropbox URL
      facebook: cleanSocial(Facebook),
      instagram: cleanSocial(Instagram),
      twitter: cleanSocial(Twitter),
      linkedin: cleanSocial(Linkedin),
      tiktok: cleanSocial(Tiktok),
      youtube: cleanSocial(Youtube),
    };

    let result;
    let action;

    if (existingProfile) {
      // Update existing profile
      result = await SettingProfile.findOneAndUpdate(
        { submittedBy: userId },
        profileData,
        { new: true, runValidators: true } // Return updated document and run validators
      );
      action = "updated";
      console.log("Profile updated for user:", userId);
    } else {
      // Create new profile
      result = await SettingProfile.create({
        submittedBy: userId,
        ...profileData
      });
      action = "created";
      console.log("Profile created for user:", userId);
    }

    res.status(200).json({ 
      message: `Profile ${action} successfully`, 
      data: result,
      action: action
    });

  } catch (err) {
    console.error("Error:", err);

    // Handle duplicate key error (code 11000)
    if (err?.code === 11000) {
      const duplicateField = Object.keys(err.keyValue)[0];
      const duplicateValue = err.keyValue[duplicateField];
      
      console.log(`Duplicate error - Field: ${duplicateField}, Value: ${duplicateValue}`);
      
      // Handle null duplicates (for both Username and URL fields)
      const isNullDuplicate = duplicateValue === null || duplicateValue === undefined || duplicateValue === "";
      const isUsernameField = duplicateField === 'username' || duplicateField === 'Username';
      const isUrlField = duplicateField === 'url' || duplicateField === 'URL';
      
      if (isNullDuplicate && (isUsernameField || isUrlField)) {
        console.log(`⚠️  Null ${duplicateField} duplicate detected. Cleaning up...`);
        
        try {
          // Drop old indexes
          const indexesToDrop = ['Username_1', 'username_1', 'URL_1', 'url_1'];
          for (const indexName of indexesToDrop) {
            try {
              await SettingProfile.collection.dropIndex(indexName);
              console.log(`✅ Dropped old ${indexName} index`);
            } catch (indexErr) {
              // Index doesn't exist, continue
            }
          }

          // Delete ALL profiles with null/empty username or URL
          const deleteResult = await SettingProfile.deleteMany({
            $or: [
              { username: null },
              { username: { $exists: false } },
              { username: "" },
              { Username: null },
              { Username: { $exists: false } },
              { Username: "" },
              { url: null },
              { url: { $exists: false } },
              { url: "" },
              { URL: null },
              { URL: { $exists: false } },
              { URL: "" }
            ]
          });
          
          console.log(`✅ Deleted ${deleteResult.deletedCount} profiles with null/empty fields`);
          
          // Retry creating the profile
          const result = await SettingProfile.create({
            submittedBy: userId,
            username: req.body.Username,
            displayName: req.body.DisplayName,
            url: req.body.URL || undefined,
            profile: req.body.Profile,
            country: req.body.Country,
            profilePhoto: req.body.ProfilePhoto,
            facebook: cleanSocial(req.body.Facebook),
            instagram: cleanSocial(req.body.Instagram),
            twitter: cleanSocial(req.body.Twitter),
            linkedin: cleanSocial(req.body.Linkedin),
            tiktok: cleanSocial(req.body.Tiktok),
            youtube: cleanSocial(req.body.Youtube),
          });
          
          return res.status(200).json({ 
            message: "Profile created successfully after cleanup", 
            data: result,
            action: "created"
          });
          
        } catch (cleanupError) {
          console.error("❌ Cleanup failed:", cleanupError);
          return res.status(500).json({ 
            message: "Failed to create profile after cleanup", 
            error: cleanupError.message 
          });
        }
      }
      
      // For other duplicate errors (non-null values)
      return res.status(400).json({ 
        message: "Duplicate value", 
        field: Object.keys(err.keyValue),
        details: err.keyValue 
      });
    }

    if (err?.name === "ValidationError") {
      const errorDetails = {};
      Object.keys(err.errors).forEach(key => {
        errorDetails[key] = err.errors[key].message;
      });
      
      return res.status(400).json({
        message: "Validation failed",
        errors: errorDetails,
        receivedData: req.body
      });
    }

    res.status(500).json({ 
      message: "Server error", 
      error: err.message 
    });
  }
});


// GET user profile for dashboard
// GET user profile and submission counts for dashboard

router.get("/dashboard", authenticate, async (req, res) => {
  try {
    const userId = req.user.id;

    // ✅ Get user profile
    const userProfile = await SettingProfile.findOne({ submittedBy: userId })
      .select(
        "username displayName url profile country profilePhoto facebook instagram twitter linkedin tiktok youtube createdAt updatedAt"
      )
      .lean();

    // ✅ Get submission counts from all models
    const [aiWebsites, directories, websiteSubmissions] = await Promise.all([
      SubmitAiWebsite.find({ submittedBy: userId }).countDocuments(),
      SubmitDirectory.find({ submittedBy: userId }).countDocuments(),
      WebsiteSubmission.find({ submittedBy: userId }).countDocuments(),
    ]);

    // ✅ Calculate total submissions
    const totalSubmissions = aiWebsites + directories + websiteSubmissions;

    // ✅ Fetch all websites submitted by this user
    const userWebsites = await WebsiteSubmission.find({ submittedBy: userId }).select("_id");
    const websiteIds = userWebsites.map((site) => site._id);

    // ✅ Count awards for each category
    const [sotdCount, sotwCount, sotmCount, sotyCount] = await Promise.all([
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTD" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTW" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTM" }),
      Award.countDocuments({ websiteId: { $in: websiteIds }, awardType: "SOTY" }),
    ]);

    // ✅ Combine award stats
    const awardStats = {
      sotdCount,
      sotwCount,
      sotmCount,
      sotyCount,
      totalAwards: sotdCount + sotwCount + sotmCount + sotyCount,
    };

    // ✅ Prepare response data
    const dashboardData = {
      profile: userProfile,
      hasProfile: !!userProfile,
      submissionStats: {
        aiWebsites,
        directories,
        websiteSubmissions,
        totalSubmissions,
      },
      awardStats, // ← added here
    };

    console.log("✅ Dashboard data fetched for user:", userId);

    return res.status(200).json({
      message: "Dashboard data fetched successfully",
      data: dashboardData,
    });
  } catch (err) {
    console.error("❌ Error fetching dashboard data:", err);
    return res.status(500).json({
      message: "Error occurred while fetching dashboard data",
      error: err.message,
    });
  }
});

export default router;