import express from 'express';
import http from 'http';
import cors from 'cors';
import { WebSocketServer, WebSocket } from 'ws';
import path from 'path';
import { fileURLToPath } from 'node:url';
import fs from 'fs';
import { projectsRouter } from './routes/projects.js';
import { filesRouter } from './routes/files.js';
import { sessionsRouter } from './routes/sessions.js';
import { sseRouter } from './routes/sse.js';
import { codefreeApiRouter } from './routes/codefreeApi.js';
import { gitRouter } from './routes/git.js';
import { handleShellWebSocket, handleChatWebSocket } from './routes/websocket.js';
import { initializeClient, shutdownClient, getAIConfig } from './services/aiService.js';

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

const envPath = path.resolve(__dirname, '..', '.env');
if (fs.existsSync(envPath)) {
  const envContent = fs.readFileSync(envPath, 'utf-8');
  for (const line of envContent.split('\n')) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;
    const eqIndex = trimmed.indexOf('=');
    if (eqIndex === -1) continue;
    const key = trimmed.slice(0, eqIndex).trim();
    const value = trimmed.slice(eqIndex + 1).trim();
    if (!process.env[key]) {
      process.env[key] = value;
    }
  }
  console.log('[ENV] Loaded .env file');
}
const APP_ROOT = fs.existsSync(path.join(__dirname, '..', 'dist', 'index.html'))
  ? path.resolve(__dirname, '..')
  : path.resolve(__dirname, '..', '..');

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

const PORT = process.env.SERVER_PORT || 3001;

app.use(cors());
app.use(express.json({ limit: '200mb' }));
app.use(express.urlencoded({ limit: '200mb', extended: true }));

const wss = new WebSocketServer({ server });

const connectedClients = new Set();

function broadcastToClients(message) {
  const data = JSON.stringify(message);
  connectedClients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(data);
    }
  });
}

app.get('/health', (req, res) => {
  res.json({ status: 'ok', timestamp: new Date().toISOString(), service: 'CodeFree-O UI' });
});

app.use('/api/projects', projectsRouter);
app.use('/api/files', filesRouter);
app.use('/api/sessions', sessionsRouter);
app.use('/api/codefree', codefreeApiRouter);
app.use('/api/git', gitRouter);
app.use('/api/sse', sseRouter);

app.use(express.static(path.join(APP_ROOT, 'public')));
app.use(express.static(path.join(APP_ROOT, 'dist'), {
  setHeaders: (res, filePath) => {
    if (filePath.endsWith('.html')) {
      res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
    } else if (filePath.match(/\.(js|css|woff2?|ttf|eot|svg|png|jpg|jpeg|gif|ico)$/)) {
      res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
    }
  }
}));

app.get('*', (req, res) => {
  const indexPath = path.join(APP_ROOT, 'dist', 'index.html');
  if (fs.existsSync(indexPath)) {
    res.sendFile(indexPath);
  } else {
    res.status(404).json({ error: 'Not found' });
  }
});

wss.on('connection', (ws, request) => {
  const url = new URL(request.url || '', 'http://localhost');
  const pathname = url.pathname;

  console.log('[WS] Client connected to:', pathname);

  if (pathname === '/shell') {
    handleShellWebSocket(ws, request);
    return;
  }

  if (pathname === '/ws') {
    handleChatWebSocket(ws, request, connectedClients, broadcastToClients);
    return;
  }

  connectedClients.add(ws);
  ws.on('close', () => {
    connectedClients.delete(ws);
  });

  ws.on('message', (data) => {
    try {
      const message = JSON.parse(data.toString());
      console.log('[WS] Received:', message.type);
    } catch (e) {
      console.error('[WS] Invalid message:', e.message);
    }
  });
});

async function startServer() {
  try {
    console.log('[AI] Initializing CodeFree-O backend...');
    await initializeClient();
  } catch (error) {
    console.error('[AI] Failed to initialize CodeFree-O backend:', error.message);
    console.error('[AI] Make sure "codefree-o" CLI is installed and available in PATH.');
    console.error('[AI] You can install it with: npm install -g @srdcloud/codefree-o');
  }

  const config = getAIConfig();
  server.listen(PORT, () => {
    console.log(`\n  ╔══════════════════════════════════════════════════╗`);
    console.log(`  ║   CodeFree-O UI Server                          ║`);
    console.log(`  ║   http://localhost:${PORT}                           ║`);
    console.log(`  ║   Service URL:  ${config.baseUrl.padEnd(35)}║`);
    console.log(`  ║   API Key:      ${(config.apiKeyConfigured ? '✓ 已配置' : '✗ 未配置').padEnd(35)}║`);
    console.log(`  ║   Directory:    ${(config.directory || '(default)').padEnd(35)}║`);
    console.log(`  ╚══════════════════════════════════════════════════╝\n`);
  });
}

startServer();

process.on('SIGINT', async () => {
  await shutdownClient();
  process.exit(0);
});

process.on('SIGTERM', async () => {
  await shutdownClient();
  process.exit(0);
});

export { app, server, wss, broadcastToClients, connectedClients };
