import express from 'express';
import cors from 'cors';
import session from 'express-session';
import passport from 'passport';
import { Strategy as SteamStrategy } from 'passport-steam';
import dotenv from 'dotenv';
import { promises as fs } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

dotenv.config();

const app = express();
const PORT = process.env.PORT || 3001;
const FRONTEND_URL = process.env.FRONTEND_URL || 'http://localhost:5173';
const VOTES_FILE = path.join(process.cwd(), 'votes.json');
const PRODUCTION_DOMAIN = process.env.DOMAIN || 'https://s22.ethanf.gg';

// Poll ends at 11:59 PM Eastern Time on 8/21/25
const POLL_END_DATE = new Date("2025-08-21T23:59:59-04:00");

function isPollEnded() {
  return new Date() > POLL_END_DATE;
}


// Helper functions for vote storage
async function loadVotes() {
  try {
    const data = await fs.readFile(VOTES_FILE, 'utf8');
    return JSON.parse(data);
  } catch (error) {
    // File doesn't exist or is empty, return empty object
    return {};
  }
}

async function saveVotes(votes) {
  await fs.writeFile(VOTES_FILE, JSON.stringify(votes, null, 2));
}

// Middleware
app.use(cors({
  origin: process.env.NODE_ENV === 'production' 
    ? PRODUCTION_DOMAIN
    : FRONTEND_URL,
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'Cookie'],
  exposedHeaders: ['Set-Cookie']
}));

app.use(express.json());
app.use(session({
  secret: process.env.SESSION_SECRET || 'your-secret-key-change-this',
  resave: false,
  saveUninitialized: true,
  rolling: true,
  cookie: {
    secure: process.env.NODE_ENV === 'production',
    maxAge: 24 * 60 * 60 * 1000, // 24 hours
    httpOnly: true,
    sameSite: process.env.NODE_ENV === 'production' ? 'lax' : 'lax'
  },
  name: 's22poll.sid'
}));

app.use(passport.initialize());
app.use(passport.session());

// Serve static files from React build in production
if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, '../dist')));
}

// Passport Steam Strategy
passport.use(new SteamStrategy({
    returnURL: process.env.NODE_ENV === 'production' 
      ? `${PRODUCTION_DOMAIN}/auth/steam/return`
      : 'http://localhost:3001/auth/steam/return',
    realm: process.env.NODE_ENV === 'production' 
      ? PRODUCTION_DOMAIN
      : 'http://localhost:3001/',
    apiKey: process.env.STEAM_API_KEY
  },
  function(identifier, profile, done) {
    const user = {
      steamId: profile.id,
      displayName: profile.displayName,
      avatar: profile.photos[0].value,
      profileUrl: profile._json.profileurl
    };
    return done(null, user);
  }
));

passport.serializeUser((user, done) => {
  done(null, user);
});

passport.deserializeUser((user, done) => {
  done(null, user);
});

// Routes
app.get('/auth/steam', passport.authenticate('steam'));

app.get('/auth/steam/return',
  passport.authenticate('steam', { failureRedirect: '/' }),
  (req, res) => {
    console.log('User authenticated:', req.user);
    console.log('Session ID:', req.sessionID);
    console.log('Session:', req.session);
    console.log('Request host:', req.get('host'));
    console.log('Request headers:', req.headers);
    console.log('Response will set cookie for domain:', req.get('host'));
    
    // Explicitly save the session before redirecting
    req.session.save((err) => {
      if (err) {
        console.error('Session save error:', err);
        return res.redirect('/');
      }
      console.log('Session saved successfully');
      
      // In production, redirect to root since frontend and backend are on same domain
      const redirectUrl = process.env.NODE_ENV === 'production' ? '/' : FRONTEND_URL;
      console.log('Redirecting to:', redirectUrl);
      res.redirect(redirectUrl);
    });
  }
);

app.post('/auth/logout', (req, res) => {
  req.logout((err) => {
    if (err) {
      return res.status(500).json({ error: 'Logout failed' });
    }
    res.json({ message: 'Logged out successfully' });
  });
});

app.get('/auth/user', (req, res) => {
  console.log('Auth check - Session ID:', req.sessionID);
  console.log('Auth check - Is authenticated:', req.isAuthenticated());
  console.log('Auth check - User:', req.user);
  console.log('Auth check - Session:', req.session);
  console.log('Auth check - Request host:', req.get('host'));
  console.log('Auth check - Cookies:', req.headers.cookie);
  if (req.isAuthenticated()) {
    res.json({ user: req.user });
  } else {
    res.json({ user: null });
  }
});

// Debug endpoint to test cookies
app.get('/debug/cookies', (req, res) => {
  res.json({
    sessionID: req.sessionID,
    cookies: req.headers.cookie,
    session: req.session,
    isAuthenticated: req.isAuthenticated(),
    user: req.user
  });
});

// Vote submission endpoint
app.post('/api/submit-vote', async (req, res) => {
  if (!req.isAuthenticated()) {
    return res.status(401).json({ error: 'Must be logged in to vote' });
  }

  // Check if poll has ended
  if (isPollEnded()) {
    return res.status(400).json({ 
      error: 'The poll has ended',
      pollEndDate: POLL_END_DATE.toISOString()
    });
  }

  const { vote } = req.body;
  const user = req.user;

  try {
    // Load existing votes
    const votes = await loadVotes();
    
    // Check if user has already voted
    if (votes[user.steamId]) {
      return res.status(400).json({ error: 'You have already submitted a vote' });
    }

    // Save the vote
    votes[user.steamId] = {
      steamId: user.steamId,
      displayName: user.displayName,
      vote: vote,
      timestamp: new Date().toISOString()
    };

    await saveVotes(votes);

    console.log(`Vote submitted by ${user.displayName} (${user.steamId}):`, vote);

    res.json({ 
      success: true, 
      message: 'Vote submitted successfully',
      user: user.displayName 
    });
  } catch (error) {
    console.error('Error saving vote:', error);
    res.status(500).json({ error: 'Failed to save vote' });
  }
});

// Check if user has already voted
app.get('/api/vote-status', async (req, res) => {
  if (!req.isAuthenticated()) {
    return res.status(401).json({ error: 'Not authenticated' });
  }

  try {
    const votes = await loadVotes();
    const userVote = votes[req.user.steamId];
    
    res.json({ 
      hasVoted: !!userVote,
      vote: userVote ? userVote.vote : null,
      timestamp: userVote ? userVote.timestamp : null,
      isPollEnded: isPollEnded(),
      pollEndDate: POLL_END_DATE.toISOString()
    });
  } catch (error) {
    console.error('Error checking vote status:', error);
    res.status(500).json({ error: 'Failed to check vote status' });
  }
});

// Get vote results (admin endpoint - you might want to add authentication)
app.get('/api/results', async (req, res) => {
  try {
    const votes = await loadVotes();
    const voteArray = Object.values(votes);
    
    // Calculate results
    const mapCounts = {};
    const totalVotes = voteArray.length;
    
    voteArray.forEach(voteData => {
      voteData.vote.forEach((map, index) => {
        if (!mapCounts[map.name]) {
          mapCounts[map.name] = { name: map.name, positions: [0, 0, 0, 0], totalScore: 0 };
        }
        mapCounts[map.name].positions[index]++;
        // Higher position = higher score (4 points for 1st, 3 for 2nd, etc.)
        mapCounts[map.name].totalScore += (4 - index);
      });
    });

    res.json({
      totalVotes,
      results: Object.values(mapCounts).sort((a, b) => b.totalScore - a.totalScore)
    });
  } catch (error) {
    console.error('Error getting results:', error);
    res.status(500).json({ error: 'Failed to get results' });
  }
});

if (process.env.NODE_ENV === 'production') {
  app.get('*', (req, res) => {
    res.sendFile(path.join(__dirname, '../dist/index.html'));
  });
}

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
  console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
});