import express from 'express';
import path from 'path';
import fs from 'fs/promises';
import { fileURLToPath } from 'url';
import process from 'process';

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

const app = express();
app.use(express.json({ limit: '20mb' }));

const PORT = parseInt(process.env.PORT || process.env.HTTPS_PORT || '2093', 10);
const publicDir = path.join(__dirname, '..', 'public');
const snapshotsDir = path.join(publicDir, 'snapshots');
const WEBCAM_URL = process.env.WEBCAM_URL || '';
const BODYTRACKER_URL = process.env.BODYTRACKER_URL || '';

app.use(express.static(publicDir));

app.get('/api/health', (req, res) => {
  res.json({ ok: true, mode: 'backend-proxy', webcamUrl: WEBCAM_URL || null, bodyTrackerUrl: BODYTRACKER_URL || null });
});

async function findLatestSnapshotFile() {
  const files = await fs.readdir(snapshotsDir);
  const entries = await Promise.all(
    files
      .filter((name) => name.endsWith('.csv'))
      .map(async (name) => ({
        name,
        mtime: (await fs.stat(path.join(snapshotsDir, name))).mtime.valueOf()
      }))
  );
  if (entries.length === 0) return null;
  entries.sort((a, b) => b.mtime - a.mtime);
  return entries[0].name;
}

app.get('/api/latest-snapshot', async (req, res) => {
  try {
    if (WEBCAM_URL) {
      const url = new URL('/api/latest-snapshot', WEBCAM_URL).toString();
      const fetchRes = await fetch(url);
      const contentType = fetchRes.headers.get('content-type') || '';

      if (!fetchRes.ok) {
        const text = await fetchRes.text();
        return res.status(fetchRes.status).type('text/plain').send(text);
      }

      if (contentType.includes('application/json')) {
        const body = await fetchRes.json();
        return res.json(body);
      }

      const text = await fetchRes.text();
      return res.json({ filename: 'latest.csv', mtime: new Date().toISOString(), content: text });
    }

    const latestFile = await findLatestSnapshotFile();
    if (!latestFile) {
      return res.status(404).json({ error: 'Keine Snapshot-CSV-Datei gefunden' });
    }

    const baseName = path.basename(latestFile, path.extname(latestFile));
    const csvPath = path.join(snapshotsDir, latestFile);
    const jsonPath = path.join(snapshotsDir, `${baseName}.json`);
    const imagePath = path.join(snapshotsDir, `${baseName}_annotated.jpg`);
    const imagePath2 = path.join(snapshotsDir, `${baseName}_annotated2.jpg`);

    const content = await fs.readFile(csvPath, 'utf8');
    const result = { filename: latestFile, mtime: (await fs.stat(csvPath)).mtime.toISOString(), content };

    try {
      result.jsonFile = { filename: `${baseName}.json`, content: await fs.readFile(jsonPath, 'utf8') };
    } catch {}

    try {
      const jpg = await fs.readFile(imagePath);
      result.imageFile = {
        filename: path.basename(imagePath),
        mimeType: 'image/jpeg',
        contentBase64: jpg.toString('base64')
      };
    } catch {}

    try {
      const jpg2 = await fs.readFile(imagePath2);
      result.image2 = {
        filename: path.basename(imagePath2),
        mimeType: 'image/jpeg',
        contentBase64: jpg2.toString('base64')
      };
    } catch {}

    return res.json(result);
  } catch (err) {
    console.error('latest-snapshot error:', err);
    return res.status(500).json({ error: 'Fehler beim Laden des Snapshots', details: String(err) });
  }
});

app.post('/api/estimate', async (req, res) => {
  if (!BODYTRACKER_URL) {
    return res.status(501).json({ error: 'BODYTRACKER_URL ist nicht konfiguriert' });
  }

  try {
    const { imageFile, image2, robotIntrinsics } = req.body;
    const formData = new FormData();

    if (imageFile?.contentBase64) {
      const buffer = Buffer.from(imageFile.contentBase64, 'base64');
      formData.append('images', new Blob([buffer], { type: imageFile.mimeType || 'image/jpeg' }), imageFile.filename || 'snapshot.jpg');
    }

    if (image2?.contentBase64) {
      const buffer2 = Buffer.from(image2.contentBase64, 'base64');
      formData.append('images', new Blob([buffer2], { type: image2.mimeType || 'image/jpeg' }), image2.filename || 'snapshot2.jpg');
    }

    if (robotIntrinsics) {
      formData.append('intrinsics', new Blob([JSON.stringify(robotIntrinsics)], { type: 'application/json' }), 'intrinsics.json');
    }

    const estimateUrl = new URL('/v1/estimate', BODYTRACKER_URL).toString();
    const fetchRes = await fetch(estimateUrl, { method: 'POST', body: formData });

    if (!fetchRes.ok) {
      const message = await fetchRes.text();
      return res.status(fetchRes.status).json({ error: 'BodyTracker-Fehler', details: message });
    }

    const body = await fetchRes.json();
    return res.json(body);
  } catch (err) {
    console.error('estimate error:', err);
    return res.status(500).json({ error: 'Fehler beim Aufruf des BodyTracker', details: String(err) });
  }
});

async function checkServiceReachability(name, url) {
  try {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 5000);
    const res = await fetch(url, { signal: controller.signal });
    clearTimeout(timeout);

    if (!res.ok) {
      console.warn(`${name} ist nicht vollständig erreichbar (${res.status}) unter ${url}`);
      return false;
    }

    console.log(`${name} erreichbar unter ${url}`);
    return true;
  } catch (err) {
    console.warn(`${name} konnte nicht erreicht werden unter ${url}:`, err.message || err);
    return false;
  }
}

async function startServer() {
  if (WEBCAM_URL) {
    await checkServiceReachability('WEBCAM_URL', new URL('/health', WEBCAM_URL).toString());
  }

  if (BODYTRACKER_URL) {
    await checkServiceReachability('BODYTRACKER_URL', new URL('/v1/health', BODYTRACKER_URL).toString());
  }

  app.listen(PORT, () => {
    console.log(`appRobotHoming backend listening on port ${PORT}`);
    console.log(`WEBCAM_URL=${WEBCAM_URL || '<lokal>'}`);
    console.log(`BODYTRACKER_URL=${BODYTRACKER_URL || '<nicht konfiguriert>'}`);
  });
}

startServer().catch((err) => {
  console.error('Fehler beim Starten des Servers:', err);
  console.log('Starte trotzdem den Server weiter...');
  app.listen(PORT, () => {
    console.log(`appRobotHoming backend listening on port ${PORT}`);
    console.log(`WEBCAM_URL=${WEBCAM_URL || '<lokal>'}`);
    console.log(`BODYTRACKER_URL=${BODYTRACKER_URL || '<nicht konfiguriert>'}`);
  });
});
