import express, { Request, Response } from 'express';
import multer from 'multer';
import path from 'path';
import fs from 'fs';

const app = express();
const PORT = 3000;

// ── Storage config ──────────────────────────────────────────────
const storage = multer.diskStorage({
  destination: (req: Request, _file, cb) => {
    const type = (req.query.type as string) || 'ingredients';
    const dir = path.join(__dirname, '..', 'public', 'images', type);
    fs.mkdirSync(dir, { recursive: true });
    cb(null, dir);
  },
  filename: (_req, file, cb) => {
    const ext = path.extname(file.originalname);
    const name = path.basename(file.originalname, ext)
      .toLowerCase()
      .replace(/\s+/g, '_');
    cb(null, name + ext);
  },
});
const upload = multer({ storage, limits: { fileSize: 5 * 1024 * 1024 } });

// ── Static files ─────────────────────────────────────────────────
app.use(express.static(path.join(__dirname, '..', 'public')));
app.use(express.json());

// ── Types ─────────────────────────────────────────────────────────
interface Ingredient {
  name: string;
  image: string;
}

interface GridSlot {
  slot: number;          // 0-8, left-to-right, top-to-bottom
  ingredient: Ingredient;
  revealedByDefault: boolean;
}

interface Recipe {
  id: string;
  name: string;
  result: { name: string; image: string };
  grid: GridSlot[];
}

// ── Config path ───────────────────────────────────────────────────
const RECIPES_PATH = path.join(__dirname, '..', 'config', 'recipes.json');

function loadRecipes(): Recipe[] {
  try {
    return JSON.parse(fs.readFileSync(RECIPES_PATH, 'utf-8'));
  } catch {
    return [];
  }
}

function saveRecipes(recipes: Recipe[]): void {
  fs.writeFileSync(RECIPES_PATH, JSON.stringify(recipes, null, 2));
}

// ── Routes ────────────────────────────────────────────────────────

// GET all recipes
app.get('/api/recipes', (_req: Request, res: Response) => {
  res.json(loadRecipes());
});

// GET single recipe
app.get('/api/recipes/:id', (req: Request, res: Response) => {
  const recipes = loadRecipes();
  const recipe = recipes.find(r => r.id === req.params.id);
  if (!recipe) { res.status(404).json({ error: 'Recipe not found' }); return; }
  res.json(recipe);
});

// POST create recipe
app.post('/api/recipes', (req: Request, res: Response) => {
  const recipes = loadRecipes();
  const recipe: Recipe = req.body;

  if (!recipe.id || !recipe.name || !recipe.result || !recipe.grid) {
    res.status(400).json({ error: 'Missing required fields: id, name, result, grid' });
    return;
  }

  if (recipes.find(r => r.id === recipe.id)) {
    res.status(409).json({ error: `Recipe with id "${recipe.id}" already exists` });
    return;
  }

  recipes.push(recipe);
  saveRecipes(recipes);
  res.status(201).json(recipe);
});

// PUT update recipe
app.put('/api/recipes/:id', (req: Request, res: Response) => {
  const recipes = loadRecipes();
  const idx = recipes.findIndex(r => r.id === req.params.id);
  if (idx === -1) { res.status(404).json({ error: 'Recipe not found' }); return; }
  recipes[idx] = { ...recipes[idx], ...req.body, id: req.params.id };
  saveRecipes(recipes);
  res.json(recipes[idx]);
});

// DELETE recipe
app.delete('/api/recipes/:id', (req: Request, res: Response) => {
  const recipes = loadRecipes();
  const idx = recipes.findIndex(r => r.id === req.params.id);
  if (idx === -1) { res.status(404).json({ error: 'Recipe not found' }); return; }
  recipes.splice(idx, 1);
  saveRecipes(recipes);
  res.json({ success: true });
});

// POST upload image (?type=ingredients|results)
app.post('/api/upload', upload.single('image'), (req: Request, res: Response) => {
  if (!req.file) { res.status(400).json({ error: 'No file uploaded' }); return; }
  const type = (req.query.type as string) || 'ingredients';
  const url = `/images/${type}/${req.file.filename}`;
  res.json({ url, filename: req.file.filename });
});

// GET list uploaded images
app.get('/api/images', (_req: Request, res: Response) => {
  const base = path.join(__dirname, '..', 'public', 'images');
  const result: Record<string, string[]> = { ingredients: [], results: [] };
  for (const type of ['ingredients', 'results']) {
    const dir = path.join(base, type);
    if (fs.existsSync(dir)) {
      result[type] = fs.readdirSync(dir)
        .filter(f => /\.(png|jpg|jpeg|gif|webp)$/i.test(f))
        .map(f => `/images/${type}/${f}`);
    }
  }
  res.json(result);
});

// ── Start ─────────────────────────────────────────────────────────
app.listen(PORT, () => {
  console.log(`\n🟩 Minecraft Craft Reveal`);
  console.log(`   ➜  http://localhost:${PORT}`);
  console.log(`   ➜  API: http://localhost:${PORT}/api/recipes\n`);
});
