import express from 'express';
import { createServer } from 'http';
import { Server as SocketIOServer } from 'socket.io';
import cookieParser from 'cookie-parser';
import session from 'express-session';
import cors from 'cors';
import { fileURLToPath, URL as NodeURL } from 'url';
import { dirname, join } from 'path';
import { setupBroadcast } from './broadcast.js';
import { setupRoutes } from './routes.js';
import { setupSEORoutes } from './routes-seo.js';

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

const app = express();
const server = createServer(app);

// Umgebungsvariablen
const NODE_ENV = process.env.NODE_ENV || 'development';
const PORT = process.env.PORT || (NODE_ENV === 'production' ? 4000 : 3300);
const IS_PRODUCTION = NODE_ENV === 'production';
const PRIMARY_HOST = 'www.ypchat.net';
const LEGACY_HOSTS = new Set(['ypchat.net']);

// CORS-Origins konfigurieren
const allowedOrigins = IS_PRODUCTION
  ? ['https://www.ypchat.net', 'https://ypchat.net']
  : ['http://localhost:5175', 'http://127.0.0.1:5175'];

// Socket.IO auf dem gleichen HTTP-Server wie Express
const io = new SocketIOServer(server, {
  cors: {
    origin: allowedOrigins,
    credentials: true,
    methods: ['GET', 'POST']
  },
  transports: ['websocket', 'polling'],
  allowEIO3: true,
  maxHttpBufferSize: 10 * 1024 * 1024, // 10MB für große Bilder (Base64-kodiert)
  pingTimeout: 60000,
  pingInterval: 25000
});

console.log('Socket.IO Server initialisiert auf Express-Server');
console.log('Umgebung:', NODE_ENV);
console.log('CORS erlaubt für:', allowedOrigins);

// CORS-Konfiguration
app.use(cors({
  origin: (origin, callback) => {
    // Erlaube Requests ohne Origin (z.B. Postman, mobile Apps)
    if (!origin) return callback(null, true);

    if (allowedOrigins.includes(origin) || !IS_PRODUCTION) {
      callback(null, true);
    } else {
      callback(new Error('Nicht erlaubt durch CORS'));
    }
  },
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

// Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());

// Session-Konfiguration
const sessionSecret = process.env.SESSION_SECRET || 'singlechat-secret-key-change-in-production';
app.use(session({
  secret: sessionSecret,
  resave: false,
  saveUninitialized: false,
  cookie: {
    secure: IS_PRODUCTION, // true für HTTPS in Production
    httpOnly: true,
    maxAge: 24 * 60 * 60 * 1000, // 24 Stunden
    sameSite: IS_PRODUCTION ? 'lax' : false // Lax für HTTPS, false für Development
  }
}));

// Trust Proxy für Apache Reverse Proxy (muss vor Routes stehen)
if (IS_PRODUCTION) {
  app.set('trust proxy', 1); // Vertraue dem ersten Proxy (Apache)

  // SEO-Fallback: erzwinge kanonischen Host + HTTPS, falls der Proxy es nicht bereits tut.
  app.use((req, res, next) => {
    const forwardedHost = String(req.headers['x-forwarded-host'] || '')
      .split(',')[0]
      .trim()
      .toLowerCase();
    const rawHost = String(req.headers.host || '')
      .split(':')[0]
      .trim()
      .toLowerCase();
    const host = forwardedHost || rawHost;

    const forwardedProto = String(req.headers['x-forwarded-proto'] || '')
      .split(',')[0]
      .trim()
      .toLowerCase();
    const isHttps = forwardedProto ? forwardedProto === 'https' : req.secure;
    const isKnownPublicHost = host === PRIMARY_HOST || LEGACY_HOSTS.has(host);

    if (!isKnownPublicHost) {
      next();
      return;
    }

    if (!isHttps || host !== PRIMARY_HOST) {
      res.redirect(301, `https://${PRIMARY_HOST}${req.originalUrl || '/'}`);
      return;
    }

    next();
  });

  // Tracking-/Session-Query entfernen (wtd, js=no), damit Google keine Duplikat-URLs indexiert.
  // Suchkonsole: "Alternative Seite mit richtigem kanonischen Tag" fuer /?wtd=... verschwindet nach Neu-Crawl.
  app.use((req, res, next) => {
    if (req.method !== 'GET' && req.method !== 'HEAD') {
      next();
      return;
    }
    if (req.path.startsWith('/api')) {
      next();
      return;
    }
    const host = req.get('host') || 'localhost';
    const proto = req.get('x-forwarded-proto') || req.protocol || 'https';
    const raw = req.originalUrl.split('#')[0];
    let u;
    try {
      u = new NodeURL(raw, `${proto}://${host}`);
    } catch {
      next();
      return;
    }
    const hadWtd = u.searchParams.has('wtd');
    const hadJsNo = u.searchParams.get('js') === 'no';
    if (!hadWtd && !hadJsNo) {
      next();
      return;
    }
    if (hadWtd) u.searchParams.delete('wtd');
    if (hadJsNo) u.searchParams.delete('js');
    const search = u.searchParams.toString();
    const dest = u.pathname + (search ? `?${search}` : '');
    if (dest !== raw) {
      res.redirect(301, dest);
      return;
    }
    next();
  });
}

// Statische Dateien aus docroot
app.use('/static', express.static(join(__dirname, '../docroot')));

// Service Worker unter Root ausliefern (wird oft für Ad‑Provider Verifikation verlangt)
app.get('/sw.js', (req, res) => {
  try {
    res.setHeader('Content-Type', 'application/javascript');
    res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    res.sendFile(join(__dirname, '../sw.js'));
  } catch (err) {
    res.status(404).send('Not found');
  }
});

// SEO-Routes (robots.txt, sitemap.xml, Pre-Rendering)
// Müssen vor anderen Routes stehen, damit sie nicht vom SPA-Fallback abgefangen werden
setupSEORoutes(app, __dirname);

// API Routes (müssen vor SPA-Fallback stehen)
setupRoutes(app, __dirname);

// Socket.IO-Handling
setupBroadcast(io, __dirname);

// In Production: Serviere auch die gebauten Client-Dateien
// SPA-Fallback muss nach allen anderen Routen stehen
if (IS_PRODUCTION) {
  const distPath = join(__dirname, '../docroot/dist');
  const KNOWN_SPA_ROUTES = new Set([
    '/',
    '/partners',
    '/feedback',
    '/faq',
    '/regeln',
    '/sicherheit',
    '/datenschutz',
    '/ratgeber',
    '/ratgeber/erste-nachricht',
    '/ratgeber/profil-tipps',
    '/ratgeber/sicher-chatten',
    '/ratgeber/red-flags',
    '/mockup-redesign'
  ]);
  app.use(express.static(distPath));
  // Fallback für Vue Router (SPA) - muss am Ende stehen
  app.get('*', (req, res) => {
    // Hinweis: SEO-Routen (/, /partners, …) werden bereits von setupSEORoutes registriert
    // und greifen vor diesem Catch-All. Kein frühes return ohne res.* hier.

    // In Production: /src/ Pfade sollten nicht existieren (404)
    if (IS_PRODUCTION && req.path.startsWith('/src/')) {
      res.status(404).send('Not found');
      return;
    }
    // Nur bekannte SPA-Routen als index.html ausliefern, unbekannte Routen mit 404 beantworten
    if (
      !req.path.startsWith('/api') &&
      !req.path.startsWith('/static') &&
      req.path !== '/robots.txt' &&
      req.path !== '/sitemap.xml' &&
      KNOWN_SPA_ROUTES.has(req.path)
    ) {
      res.sendFile(join(distPath, 'index.html'));
    } else {
      res.status(404).send('Not found');
    }
  });
}

// Server starten
// In Production laeuft Apache als Reverse Proxy auf localhost.
// In Development kann HOST=0.0.0.0 gesetzt werden, damit echte Android-Geraete
// im selben WLAN den lokalen Server erreichen.
const HOST = process.env.HOST || '127.0.0.1';

server.listen(PORT, HOST, () => {
  console.log(`Server läuft auf http://${HOST}:${PORT}`);
  console.log(`Umgebung: ${NODE_ENV}`);
  console.log(`CORS erlaubt für: ${allowedOrigins.join(', ')}`);
  if (IS_PRODUCTION) {
    console.log('Production-Modus: HTTPS über Apache Reverse Proxy');
  }
});
