import { Request, Response, NextFunction, RequestHandler } from "express";
import multer from "multer";

import { User } from "../models/User";
import { Setting } from "../models/Setting";
import { generateContent } from "../scripts/content-generator";
import { Language } from "../models/Language";
import { Blogs } from "../models/Blogs";
import { ToolPage } from "../models/ToolPage";
import { CustomPage } from "../models/CustomPage";
import { generateSettings } from "../scripts/settings-generator";
import path from "path";
import fs from "fs";

const isProduction = process.env.NODE_ENV === "production";
const baseDir = path.join(__dirname, "..", "..", "..");
const UPLOAD_DIR = isProduction
  ? path.join(baseDir, "nytsolvers", "dist", "client", "images")
  : path.join(baseDir, "project", "public", "images");

function deleteUploadedFile(filename: string) {
  const fullPath = path.join(UPLOAD_DIR, filename);
  if (fs.existsSync(fullPath)) {
    fs.unlinkSync(fullPath);
  }
}

declare module "express" {
  interface Request {
    user?: { id: number; email: string };
  }
}

export class SettingsController {
  get: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const settings = await Setting.query().first();

      const parsedSettings = settings.sites_settings || {};
      const selectedLangCodes = parsedSettings.selected_languages || [];

      const languages = await Language.query()
        .whereIn("lang_code", selectedLangCodes)
        .select("lang_code", "name");

      const languageLabels: { [key: string]: string } = {};
      for (const lang of languages) {
        if (lang.lang_code) {
          languageLabels[lang.lang_code] = lang.name;
        }
      }

      res.json({
        message: "Settings fetched successfully",
        settings,
        language_labels: languageLabels, // ✅ add this
      });
    } catch (error) {
      console.error(error);
      res.status(500).json({ message: "Error fetching settings" });
    }
  };
  show: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> => {
    try {
      const settings = await Setting.query().first();

      if (!settings || !settings.sites_settings) {
        res.status(404).json({ message: "Settings not found" });
        return;
      }

      let parsedSettings;
      try {
        parsedSettings = settings.sites_settings;
      } catch (error) {
        console.error("Error parsing sites_settings:", error);
        res.status(500).json({ message: "Invalid settings format" });
        return;
      }

      const selectedLangCodes = parsedSettings.selected_languages || [];

      const languages = await Language.query()
        .whereIn("lang_code", selectedLangCodes)
        .select("lang_code", "name");

      const languageLabels: { [key: string]: string } = {};
      for (const lang of languages) {
        if (lang.lang_code) {
          languageLabels[lang.lang_code] = lang.name;
        }
      }

      // Create a shallow copy and remove sensitive fields
      const safeSettings = { ...parsedSettings };
      delete safeSettings.api_keys; // Remove sensitive key(s)

      res.status(200).json({
        success: true,
        message: "Settings fetched successfully",
        settings: { sites_settings: JSON.stringify(safeSettings) },
        language_labels: languageLabels,
      });
    } catch (error) {
      console.error("Error fetching settings:", error);
      res
        .status(500)
        .json({ success: false, message: "Error fetching settings" });
    }
  };
  save: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ) => {
    try {
      const userId = req.user?.id; // Set by JWT middleware
      if (!userId) {
        res.status(401).json({
          isAuthenticated: false,
          message: "Not authenticated",
        });
        return;
      }

      const user = await User.query().findById(userId);
      if (!user) {
        res.status(401).json({
          isAuthenticated: false,
          message: "User not found",
        });
        return;
      }

      if (user.user_details?.role !== "admin") {
        res.status(403).json({
          isAuthenticated: true,
          message: "Access denied. Only for admin.",
        });
        return;
      }
      const settingDataRaw = req.body.sites_settings;
      const settingData =
        typeof settingDataRaw === "string"
          ? JSON.parse(settingDataRaw)
          : settingDataRaw;

      // Handle uploaded files
      const files = req.files as { [fieldname: string]: Express.Multer.File[] };
      if (files.site_logo) {
        settingData.site_logo = files.site_logo[0].filename; // Update with uploaded filename
      }
      if (files.favicon) {
        settingData.favicon = files.favicon[0].filename; // Update with uploaded filename
      }

      const existingSettings = await Setting.query().findById(1);
      let savedSettings;

      if (existingSettings) {
        const current =
          typeof existingSettings.sites_settings === "string"
            ? JSON.parse(existingSettings.sites_settings)
            : existingSettings.sites_settings;

        // Delete old site_logo if changed
        if (
          settingData.site_logo &&
          current.site_logo &&
          path.basename(settingData.site_logo) !==
            path.basename(current.site_logo)
        ) {
          deleteUploadedFile(path.basename(current.site_logo));
        }

        // Delete old favicon if changed
        if (
          settingData.favicon &&
          current.favicon &&
          path.basename(settingData.favicon) !== path.basename(current.favicon)
        ) {
          deleteUploadedFile(path.basename(current.favicon));
        }

        const mergedSettings = {
          ...current,
          ...settingData,
        };

        savedSettings = await Setting.query().patchAndFetchById(1, {
          sites_settings: JSON.stringify(mergedSettings),
          manual_sitemap_urls: settingData.manual_sitemap_urls,
        });
      } else {
        savedSettings = await Setting.query().insert({
          id: 1,
          sites_settings: JSON.stringify(settingData),
          manual_sitemap_urls: settingData.manual_sitemap_urls,
        });
      }

      await generateSettings();

      res.status(200).json({
        message: "Settings saved successfully",
        settings: savedSettings,
      });
    } catch (err: any) {
      console.error("Save settings error:", err);
      if (err.name === "ZodError") {
        res
          .status(400)
          .json({ message: "Validation Error", errors: err.errors });
      } else if (err.message.includes("Only PNG, JPEG, and ICO")) {
        res.status(400).json({ message: err.message });
      } else {
        res.status(500).json({ message: "Internal server error" });
      }
    }
  };

  generateSitemap: RequestHandler = async (
    req: Request,
    res: Response,
    next: NextFunction
  ) => {
    try {
      await generateContent();
      res.status(200).json({
        success: true,
        message: "Sitemap generated successfully with fresh dates",
      });
    } catch (err: any) {
      console.error("Sitemap generation error:", err);
      res.status(500).json({ success: false, message: "Internal server error" });
    }
  };
}