import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { tmpdir } from 'os';
import { join } from 'path';
import { promises as fs } from 'fs';
import { v4 as uuidV4 } from 'uuid';
import Epub from 'epub-gen';

const requiredEnv = [
  'SUPABASE_URL',
  'SUPABASE_SERVICE_ROLE_KEY',
  'JWT_SECRET',
  'ZAI_GLM_API_KEY',
];
requiredEnv.forEach((key) => {
  if (!process.env[key]) {
    console.error(`Missing required environment variable: ${key}`);
    process.exit(1);
  }
});

const app = express();
const PORT = process.env.PORT || 4000;
const ORIGIN = process.env.CLIENT_ORIGIN || 'http://localhost:5173';
const allowedOrigins = ORIGIN.split(',').map((origin) => origin.trim());

const USERS_TABLE = process.env.SUPABASE_USERS_TABLE || 'users';
const JWT_SECRET = process.env.JWT_SECRET;
import { supabase } from './src/services/supabaseClient.js';
import { translateWithGlm } from './src/services/glmClient.js';

app.use(
  cors({
    origin: allowedOrigins,
    credentials: true,
  }),
);
app.use(express.json({ limit: '10mb' }));

const sanitizeHtml = (text = '') =>
  text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
    .replace(/\n/g, '<br/>');

const createToken = (user) =>
  jwt.sign(
    {
      sub: user.id,
      email: user.email,
      username: user.username,
    },
    JWT_SECRET,
    { expiresIn: '7d' },
  );

const mapUserRecord = (record) => ({
  id: record.id,
  email: record.email,
  name: record.name,
  username: record.username,
});

const authMiddleware = (req, res, next) => {
  const header = req.headers.authorization || '';
  const token = header.startsWith('Bearer ') ? header.slice(7) : null;
  if (!token) {
    return res.status(401).json({ message: 'Yetkisiz erişim' });
  }
  try {
    const payload = jwt.verify(token, JWT_SECRET);
    req.user = payload;
    return next();
  } catch (error) {
    return res.status(401).json({ message: 'Oturum süresi doldu, lütfen tekrar giriş yap.' });
  }
};

const authRouter = express.Router();

authRouter.post('/register', async (req, res) => {
  const { name, email, password } = req.body || {};
  if (!name || !email || !password) {
    return res.status(400).json({ message: 'Ad, email ve şifre gereklidir.' });
  }
  const normalizedEmail = email.trim().toLowerCase();
  const username = normalizedEmail.split('@')[0];

  const { data: existingUser, error: existingError } = await supabase
    .from(USERS_TABLE)
    .select('id')
    .eq('email', normalizedEmail)
    .maybeSingle();

  if (existingError && existingError.code !== 'PGRST116') {
    return res.status(500).json({ message: 'Kullanıcı kontrolü başarısız.' });
  }

  if (existingUser) {
    return res.status(409).json({ message: 'Bu email adresi ile zaten bir hesap mevcut.' });
  }

  const passwordHash = await bcrypt.hash(password, 10);
  const { data: createdUser, error: insertError } = await supabase
    .from(USERS_TABLE)
    .insert({
      name: name.trim(),
      email: normalizedEmail,
      username,
      password_hash: passwordHash,
    })
    .select('id,email,name,username')
    .single();

  if (insertError || !createdUser) {
    return res.status(500).json({ message: 'Kullanıcı oluşturulamadı.' });
  }

  const token = createToken(createdUser);
  return res.status(201).json({ token, user: mapUserRecord(createdUser) });
});

authRouter.post('/login', async (req, res) => {
  const { email, password } = req.body || {};
  if (!email || !password) {
    return res.status(400).json({ message: 'Email ve şifre gereklidir.' });
  }

  const normalizedEmail = email.trim().toLowerCase();
  const { data: userRecord, error: fetchError } = await supabase
    .from(USERS_TABLE)
    .select('id,email,name,username,password_hash')
    .eq('email', normalizedEmail)
    .maybeSingle();

  if (fetchError && fetchError.code !== 'PGRST116') {
    return res.status(500).json({ message: 'Giriş işlemi başarısız.' });
  }
  if (!userRecord) {
    return res.status(401).json({ message: 'Email veya şifre hatalı.' });
  }

  const validPassword = await bcrypt.compare(password, userRecord.password_hash);
  if (!validPassword) {
    return res.status(401).json({ message: 'Email veya şifre hatalı.' });
  }

  const token = createToken(userRecord);
  return res.json({ token, user: mapUserRecord(userRecord) });
});

authRouter.post('/oauth', async (req, res) => {
  const { accessToken } = req.body || {};
  if (!accessToken) {
    return res.status(400).json({ message: 'Geçerli bir Google oturumu bulunamadı.' });
  }

  try {
    const response = await fetch(`${process.env.SUPABASE_URL}/auth/v1/user`, {
      headers: {
        Authorization: `Bearer ${accessToken}`,
        apikey: process.env.SUPABASE_SERVICE_ROLE_KEY,
      },
    });

    if (!response.ok) {
      return res.status(401).json({ message: 'Google oturumu doğrulanamadı.' });
    }

    const supabaseUser = await response.json();
    const email = supabaseUser?.email?.toLowerCase();
    if (!email) {
      return res.status(400).json({ message: 'Google hesabında email bilgisi bulunamadı.' });
    }
    const name =
      supabaseUser?.user_metadata?.full_name ||
      supabaseUser?.user_metadata?.name ||
      email.split('@')[0];
    const username = (supabaseUser?.user_metadata?.user_name || email.split('@')[0]).replace(/[^a-zA-Z0-9-_]/g, '');

    const { data: existingUser, error: fetchError } = await supabase
      .from(USERS_TABLE)
      .select('id,email,name,username')
      .eq('email', email)
      .maybeSingle();

    if (fetchError && fetchError.code !== 'PGRST116') {
      return res.status(500).json({ message: 'Kullanıcı sorgulanamadı.' });
    }

    let userRecord = existingUser;
    if (!userRecord) {
      const { data: insertedUser, error: insertError } = await supabase
        .from(USERS_TABLE)
        .insert({
          name,
          email,
          username,
          password_hash: 'GOOGLE_OAUTH',
        })
        .select('id,email,name,username')
        .single();

      if (insertError || !insertedUser) {
        return res.status(500).json({ message: 'Google hesabı oluşturulamadı.' });
      }
      userRecord = insertedUser;
    }

    const token = createToken(userRecord);
    return res.json({ token, user: mapUserRecord(userRecord) });
  } catch (error) {
    console.error('Google OAuth hatası:', error);
    return res.status(500).json({ message: 'Google girişi tamamlanamadı.' });
  }
});

authRouter.get('/me', authMiddleware, async (req, res) => {
  const { data: userRecord, error } = await supabase
    .from(USERS_TABLE)
    .select('id,email,name,username')
    .eq('id', req.user.sub)
    .single();

  if (error || !userRecord) {
    return res.status(404).json({ message: 'Kullanıcı bulunamadı.' });
  }

  return res.json({ user: mapUserRecord(userRecord) });
});

authRouter.post('/logout', (_req, res) => {
  return res.json({ message: 'Çıkış yapıldı.' });
});

authRouter.post('/forgot-password', async (req, res) => {
  const { email } = req.body || {};
  if (!email) {
    return res.status(400).json({ message: 'Email gereklidir.' });
  }

  // Supabase Auth kullanılmadığı için burada sadece bilgilendirici bir cevap döndürüyoruz.
  return res.json({
    message:
      'Şifre sıfırlama talebin alındı. Bu demo ortamında e-posta gönderimi aktif değildir.',
  });
});

app.use('/auth', authRouter);

app.post('/translate', async (req, res) => {
  const { text } = req.body || {};
  if (!text || !text.trim()) {
    return res.status(400).json({ message: 'Çevrilecek metin bulunamadı.' });
  }

  try {
    const translated = await translateWithGlm(text);
    return res.json({ text: translated });
  } catch (error) {
    console.error('GLM çeviri hatası:', error);
    return res.status(500).json({ message: error.message || 'Çeviri tamamlanamadı.' });
  }
});

app.post('/generate-epub', async (req, res) => {
  const { text, meta, cover } = req.body || {};
  if (!text || !text.trim()) {
    return res.status(400).json({ message: 'text is required' });
  }

  const title = meta?.title || 'imgPub OCR Export';
  const author = meta?.author || 'imgPub';
  const filename = meta?.filename || `imgpub${Date.now()}.epub`;

  const content = [
    {
      title,
      data: `<div>${sanitizeHtml(text)}</div>`,
    },
  ];

  const outputPath = join(tmpdir(), `imgpub-${uuidV4()}.epub`);
  let coverPath;

  try {
    if (cover?.data) {
      const coverBuffer = Buffer.from(cover.data, 'base64');
      const coverExtension =
        cover?.mimeType?.split('/').pop() || cover?.filename?.split('.').pop() || 'png';
      coverPath = join(tmpdir(), `imgpub-cover-${uuidV4()}.${coverExtension}`);
      await fs.writeFile(coverPath, coverBuffer);
    }

    const epubOptions = { title, author, content };
    if (coverPath) {
      epubOptions.cover = coverPath;
    }

    const epub = new Epub(epubOptions, outputPath);
    await epub.promise;
    const buffer = await fs.readFile(outputPath);
    await fs.unlink(outputPath).catch(() => {});
    if (coverPath) {
      await fs.unlink(coverPath).catch(() => {});
    }
    res.json({ filename, data: buffer.toString('base64') });
  } catch (error) {
    console.error('EPUB generation failed:', error);
    res.status(500).json({ message: 'EPUB generation failed' });
  }
});

app.get('/', (_, res) => {
  res.json({ status: 'ok' });
});

app.listen(PORT, () => {
  console.log(`imgPub EPUB server listening on port ${PORT}`);
});
