import { Router } from "express";
import fs from "node:fs/promises";
import path from "node:path";
import { getQbitCapabilities, getQbitClient } from "../qbit/qbit.context";
import { readDb } from "../storage/jsondb";
import { createLoopJob, stopLoopJob } from "./loop.engine";
import { dryRunSchema, loopStartSchema } from "../utils/validators";
import { getArchiveStatus } from "../torrent/torrent.archive";
import { config } from "../config";
import { setArchiveStatus } from "../torrent/torrent.archive";
import { nowIso } from "../utils/time";
import { readLoopLogs } from "../storage/loopLogs";

const router = Router();

router.post("/start", async (req, res) => {
  const parsed = loopStartSchema.safeParse(req.body);
  if (!parsed.success) {
    return res.status(400).json({ error: parsed.error.flatten() });
  }
  const { hash, allowIp, targetLoops, delayMs, profileName, profileId } = parsed.data;
  const db = await readDb();
  if (targetLoops > db.settings.maxLoopLimit) {
    return res.status(400).json({ error: "Target loops exceed max limit" });
  }
  const qbit = getQbitClient();
  const torrents = await qbit.getTorrentsInfo();
  const torrent = torrents.find((t) => t.hash === hash);
  if (!torrent) {
    return res.status(404).json({ error: "Torrent not found" });
  }
  let archive = await getArchiveStatus(hash);
  if (!archive?.torrentFilePath) {
    try {
      const buffer = await qbit.exportTorrent(hash);
      const targetPath = path.join(config.torrentArchiveDir, `${hash}.torrent`);
      await fs.writeFile(targetPath, buffer);
      archive = await setArchiveStatus({
        hash,
        status: "READY",
        torrentFilePath: targetPath,
        source: "exported",
        updatedAt: nowIso(),
      });
    } catch (error) {
      return res.status(400).json({
        error: "Arşiv yok ve export başarısız. Lütfen Advanced bölümünden .torrent yükleyin.",
      });
    }
  }
  const torrentFilePath = archive?.torrentFilePath;
  if (!torrentFilePath) {
    return res.status(400).json({
      error: "Arşiv dosyası bulunamadı. Lütfen tekrar yükleyin.",
    });
  }
  try {
    await fs.access(torrentFilePath);
  } catch (error) {
    return res.status(400).json({
      error: "Arşiv dosyası bulunamadı. Lütfen tekrar yükleyin.",
    });
  }
  const job = await createLoopJob({
    torrentHash: hash,
    name: torrent.name,
    sizeBytes: torrent.size,
    magnet: undefined,
    torrentFilePath,
    allowIp,
    targetLoops,
    delayMs,
    profileName,
    profileId,
  });
  res.json(job);
});

router.post("/stop/:jobId", async (req, res) => {
  const { jobId } = req.params;
  const job = await stopLoopJob(jobId);
  if (!job) {
    return res.status(404).json({ error: "Job not found" });
  }
  try {
    const qbit = getQbitClient();
    await qbit.deleteTorrent(job.torrentHash, true);
  } catch (error) {
    // Best-effort delete
  }
  res.json(job);
});

router.post("/stop-by-hash", async (req, res) => {
  const { hash } = req.body ?? {};
  if (!hash) {
    return res.status(400).json({ error: "Missing hash" });
  }
  const db = await readDb();
  const jobs = db.loopJobs.filter((j) => j.torrentHash === hash);
  if (!jobs.length) {
    return res.status(404).json({ error: "Job not found" });
  }
  const stopped = [] as any[];
  for (const job of jobs) {
    const result = await stopLoopJob(job.id);
    if (result) {
      stopped.push(result);
    }
  }
  try {
    const qbit = getQbitClient();
    await qbit.deleteTorrent(hash, true);
  } catch (error) {
    // Best-effort delete
  }
  res.json({ ok: true, stopped });
});

router.post("/dry-run", async (req, res) => {
  const parsed = dryRunSchema.safeParse(req.body);
  if (!parsed.success) {
    return res.status(400).json({ error: parsed.error.flatten() });
  }
  const { hash } = parsed.data;
  const qbit = getQbitClient();
  const caps = getQbitCapabilities();
  const torrents = await qbit.getTorrentsInfo();
  const torrent = torrents.find((t) => t.hash === hash);
  if (!torrent) {
    return res.status(404).json({ error: "Torrent not found" });
  }
  const archive = await getArchiveStatus(hash);
  res.json({
    ok: true,
    qbitVersion: caps?.version,
    capabilities: caps,
    hasMagnet: Boolean(torrent.magnet_uri),
    archiveStatus: archive?.status ?? "MISSING",
    warnings: [
      caps?.hasPeersEndpoint ? null : "Peer listing unsupported",
      caps?.hasBanEndpoint ? null : "Peer ban unsupported; warn-only enforcement",
      torrent.magnet_uri ? null : "Magnet unavailable; upload .torrent recommended",
    ].filter(Boolean),
  });
});

router.get("/jobs", async (_req, res) => {
  const db = await readDb();
  res.json(db.loopJobs);
});

router.get("/job/:jobId", async (req, res) => {
  const db = await readDb();
  const job = db.loopJobs.find((j) => j.id === req.params.jobId);
  if (!job) {
    return res.status(404).json({ error: "Job not found" });
  }
  res.json(job);
});

router.get("/logs/:jobId", async (req, res) => {
  const { jobId } = req.params;
  const logs = await readLoopLogs(jobId);
  res.json({ jobId, logs });
});

export default router;
